~netrek-developers/netrek-client-cow/trunk

« back to all changes in this revision

Viewing changes to _darcs/pristine/sound.c

  • Committer: Collin Pruitt
  • Date: 2009-05-12 04:30:09 UTC
  • Revision ID: collinp111@gmail.com-20090512043009-3jsjojoyrk16oass
Initial upload - updated from http://james.tooraweenah.com/darcs/netrek-client-cow/ using darcs (hince the existnace of _darcs), fully patched.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include "config.h"
 
2
 
 
3
#ifdef SOUND
 
4
 
 
5
#if defined(HAVE_SDL)
 
6
#include "SDL.h"
 
7
#include "SDL_mixer.h"
 
8
#endif
 
9
 
 
10
#include "copyright.h"
 
11
 
 
12
#include <stdio.h>
 
13
#include <stdlib.h>
 
14
#include <errno.h>
 
15
#include <ctype.h>
 
16
#include <time.h>
 
17
#include <sys/types.h>
 
18
#include <sys/stat.h>
 
19
#include <unistd.h>
 
20
#include INC_LIMITS
 
21
#include INC_SYS_TIME
 
22
 
 
23
#if defined(sgi)
 
24
#include <unistd.h>
 
25
#include <string.h>
 
26
#include <math.h>
 
27
#include <errno.h>
 
28
#include <fcntl.h>
 
29
#include <sys/types.h>
 
30
#include <sys/prctl.h>
 
31
#include <invent.h>
 
32
#include <dmedia/audio.h>
 
33
#include <dmedia/audiofile.h>
 
34
#include <signal.h>
 
35
#include <stropts.h>
 
36
#include <poll.h>
 
37
#include "sgi-sound.h"
 
38
#endif
 
39
 
 
40
#include "Wlib.h"
 
41
#include "defs.h"
 
42
#include "struct.h"
 
43
#include "data.h"
 
44
#include "audio.h"
 
45
 
 
46
#if defined(HAVE_SDL) || defined(sgi)
 
47
enum {
 
48
        INTRO_WAV,
 
49
        FIRE_TORP_WAV,
 
50
        PHASER_WAV,
 
51
        FIRE_PLASMA_WAV,
 
52
        EXPLOSION_WAV,
 
53
        SBEXPLOSION_WAV,
 
54
        CLOAK_WAV,
 
55
        UNCLOAK_WAV,
 
56
        SHIELD_DOWN_WAV,
 
57
        SHIELD_UP_WAV,
 
58
        TORP_HIT_WAV,
 
59
        REDALERT_WAV,
 
60
        BUZZER_WAV,
 
61
        ENTER_SHIP_WAV,
 
62
        SELF_DESTRUCT_WAV,
 
63
        PLASMA_HIT_WAV,
 
64
        MESSAGE_WAV,
 
65
        ENGINE_WAV,
 
66
        THERMAL_WAV,
 
67
        FIRE_TORP_OTHER_WAV,
 
68
        PHASER_OTHER_WAV,
 
69
        FIRE_PLASMA_OTHER_WAV,
 
70
        EXPLOSION_OTHER_WAV,
 
71
        SBEXPLOSION_OTHER_WAV,
 
72
        NUM_WAVES
 
73
};
 
74
#endif
 
75
 
 
76
#if defined(HAVE_SDL)
 
77
/* This is probably unix specific paths */
 
78
static Mix_Chunk *sounds[NUM_WAVES];
 
79
#endif
 
80
 
 
81
#if defined(sgi)
 
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);
 
95
 
 
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 };
 
112
#endif
 
113
 
 
114
#if !defined(HAVE_SDL) && !defined(sgi)
 
115
 
 
116
/* Each sound has a priority which controls what can override what
 
117
 * Currently these are set as follows:
 
118
 * 
 
119
 * 10: explosion
 
120
 * 9: phaser,plasma
 
121
 * 8: torp/plasma hit
 
122
 * 7: torp fire, cloak
 
123
 * 6: alert
 
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?)
 
127
 */
 
128
static struct Sound sounds[NUM_SOUNDS+1] = {
 
129
        {"", 0, 0},
 
130
        {"nt_fire_torp", 7, 1},
 
131
        {"nt_phaser", 9, 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},
 
140
        {"nt_engine", 0, 0},
 
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}
 
158
};
 
159
 
 
160
static char sound_prefix[PATH_MAX];
 
161
static int current_sound = NO_SOUND;
 
162
static int soundOther = 1;               /* play other ship's sounds?  */
 
163
 
 
164
#endif /* HAVE_SDL */
 
165
 
 
166
static int isDirectory(char* dir) {     /* check wheter `dir' is a directory */
 
167
        struct stat buf;
 
168
 
 
169
        if (stat(dir, &buf) < 0) {
 
170
                (void) fprintf(stderr, "stat of directory `%s' failed: %s\n", dir, strerror(errno));
 
171
                return 0;
 
172
        }
 
173
        return S_ISDIR(buf.st_mode);
 
174
}
 
175
 
 
176
#if defined(sgi)
 
177
 
 
178
/*
 
179
 * Initialize the audio hardware.
 
180
 */
 
181
int sfxInit(char *audioDir, int numPorts) {
 
182
        int idx;
 
183
        char *str;
 
184
 
 
185
        if (audioDir != NULL) {
 
186
                str = strdup(audioDir);
 
187
                if (str)
 
188
                        sfxAudioDir = str;
 
189
        }
 
190
        if (numPorts < 1)
 
191
                return SFX_ERR_NO_PORTS_AVAIL;
 
192
 
 
193
        if (numPorts > MAX_AUDIO_PORTS)
 
194
                numPorts = MAX_AUDIO_PORTS;
 
195
 
 
196
        (void) ALseterrorhandler(sfxSoundErrFunc);
 
197
 
 
198
        nAudioPorts = sfxOpenAudioPorts(audioPort, numPorts);
 
199
 
 
200
        if (nAudioPorts == 0)
 
201
                return SFX_ERR_NO_PORTS_AVAIL;
 
202
 
 
203
        if (nAudioPorts < 0)
 
204
                return SFX_ERR_NO_AUDIO_HW;
 
205
 
 
206
        (void) signal(SIGCHLD, sfxSoundDied);
 
207
 
 
208
        if (pipe(spigot) < 0 || (soundChild = sproc(sfxSoundHandler, PR_SADDR, audioPort)) < 0) {
 
209
                for (idx=0; idx < nAudioPorts; idx++)
 
210
                        ALcloseport(audioPort[idx]);
 
211
 
 
212
                return SFX_ERR_NO_SPROC;
 
213
        }
 
214
        return nAudioPorts;
 
215
}
 
216
 
 
217
/*
 
218
 * Load an audio file.
 
219
 */
 
220
Sfx sfxLoad(char *filename) {
 
221
        Sfx sp;
 
222
 
 
223
        if ((sp=(Sfx)malloc(sizeof(struct _sfx))) == NULL)
 
224
                return NULL;
 
225
 
 
226
        sp->soundData = NULL;
 
227
        sp->soundSize = NULL;
 
228
        sp->loop = 0;
 
229
        sp->repeat = 0;
 
230
        sp->count = 1;
 
231
        sp->pitch = 0;
 
232
        sp->enabled = 1;
 
233
 
 
234
        if ((sp->soundData=(short **)malloc(sizeof(short *))) == NULL) {
 
235
                sfxFree(sp);
 
236
                return NULL;
 
237
        }
 
238
        if ((sp->soundSize=(AFframecount *)malloc(sizeof(AFframecount))) == NULL) {
 
239
                sfxFree(sp);
 
240
                return NULL;
 
241
        }
 
242
        if ((sp->soundData[0] = sfxLoadAudioFile(sfxAudioDir, filename, &(sp->soundSize[0]))) == NULL) {
 
243
                sfxFree(sp);
 
244
                return NULL;
 
245
        }
 
246
        sp->id = soundId++;
 
247
        return sp;
 
248
}
 
249
 
 
250
/*
 
251
 * Indicate that a sound is to loop.
 
252
 */
 
253
void sfxLoop(Sfx sp) {
 
254
        if (sp != NULL)
 
255
                sp->loop = 1;
 
256
        return;
 
257
}
 
258
 
 
259
/*
 
260
 * Play a sound effect.
 
261
 */
 
262
void sfxPlay(Sfx sp) {
 
263
        if (sound_init && sp != NULL && sp->soundData[0] && sp->enabled) {
 
264
                if (sp->loop)
 
265
                        sp->repeat = 1;
 
266
 
 
267
                sfxCheckVolume();
 
268
                sfxSignalSound(sp);
 
269
        }
 
270
        return;
 
271
}
 
272
 
 
273
/*
 
274
 * Play a pitch-bent audio clip.
 
275
 */
 
276
void sfxPlayPitch(Sfx sp, float val) {
 
277
        int i;
 
278
 
 
279
        if (sound_init && sp != NULL && sp->soundData[0] && sp->enabled) {
 
280
                if (val <= sp->loVal)
 
281
                        i = 0;
 
282
                else if (val >= sp->hiVal)
 
283
                        i = sp->count-1;
 
284
                else
 
285
                        i = (long)(0.4f + (sp->count - 1) *
 
286
                                   (val - sp->loVal)/(sp->hiVal - sp->loVal));
 
287
 
 
288
                if (sp->loop && sp->repeat && sp->pitch == i)
 
289
                        return;
 
290
 
 
291
                sp->pitch = i;
 
292
                sfxPlay(sp);
 
293
        }
 
294
        return;
 
295
}
 
296
 
 
297
/*
 
298
 * Create a pitch bend audio clip.
 
299
 */
 
300
void sfxPitchBend(Sfx sp, float startVal, float endVal,
 
301
                          float startPitch, float endPitch,
 
302
                          float basePitch, int steps) {
 
303
        int     i, k;
 
304
        int     size;
 
305
        short   **ptr;
 
306
        short   *data;
 
307
        short   *origData;
 
308
        double  pitch;
 
309
        double  a, b;
 
310
        long    frameIndex;
 
311
        AFframecount *lptr;
 
312
 
 
313
        if (sp == NULL || steps < 2 || sp->count != 1)
 
314
                return;
 
315
 
 
316
        if ((lptr=(AFframecount *)malloc(steps * sizeof(AFframecount))) == NULL)
 
317
                return;
 
318
 
 
319
        size = 0;
 
320
        a = (endPitch - startPitch) / (double)(steps - 1);
 
321
        b = 1.0 / (double)basePitch;
 
322
 
 
323
        for (i=0; i < steps; i++) {
 
324
                pitch = (startPitch + (double)i * a) * b;
 
325
                k = (long)((double)sp->soundSize[0] / pitch);
 
326
                lptr[i] = k;
 
327
                size += k;
 
328
        }
 
329
        if ((ptr=(short **)malloc(steps * sizeof(short *))) == NULL) {
 
330
                free(lptr);
 
331
                return;
 
332
        }
 
333
 
 
334
        /*
 
335
         * Allocate new space for pitch-bent sound data.
 
336
         */
 
337
        if ((data=(short *)malloc(size * 2 * sizeof(short))) == NULL) {
 
338
                free(lptr);
 
339
                free(ptr);
 
340
                return;
 
341
        }
 
342
 
 
343
        size = (int)sp->soundSize[0];
 
344
        free(sp->soundSize);
 
345
        sp->soundSize = lptr;
 
346
 
 
347
        origData = sp->soundData[0];
 
348
        free(sp->soundData);
 
349
        sp->soundData = ptr;
 
350
 
 
351
        sp->count = steps;
 
352
        sp->loVal = startVal;
 
353
        sp->hiVal = endVal;
 
354
 
 
355
        for (i=0; i < steps; i++) {
 
356
                pitch = (startPitch + (double)i * a) * b;
 
357
 
 
358
                if (i == 0)
 
359
                        sp->soundData[i] = data;
 
360
                else
 
361
                        sp->soundData[i] = sp->soundData[i-1] + 2 * sp->soundSize[i-1];
 
362
 
 
363
                for (k=0; k < sp->soundSize[i]; k++) {
 
364
                        frameIndex = (long)(k * pitch + 0.5);
 
365
                        if (frameIndex >= size)
 
366
                                frameIndex = size - 1;
 
367
 
 
368
                        sp->soundData[i][2*k  ] = origData[2*frameIndex  ];
 
369
                        sp->soundData[i][2*k+1] = origData[2*frameIndex+1];
 
370
                }
 
371
        }
 
372
        free(origData);
 
373
        return;
 
374
}
 
375
 
 
376
/*
 
377
 * Silence an audio loop.
 
378
 */
 
379
void sfxSilenceLoop(Sfx sp) {
 
380
        if (sp != NULL && sp->repeat) {
 
381
                sp->repeat = 0;
 
382
                sfxSignalSound(sp);
 
383
        }
 
384
        return;
 
385
}
 
386
 
 
387
/*
 
388
 * Disable a sound clip.
 
389
 */
 
390
void sfxDisable(Sfx sp) {
 
391
        if (sp != NULL) {
 
392
                sp->enabled = 0;
 
393
                if (sp->loop)
 
394
                        sfxSilenceLoop(sp);
 
395
        }
 
396
        return;
 
397
}
 
398
 
 
399
/*
 
400
 * Enable a sound clip.
 
401
 */
 
402
void sfxEnable(Sfx sp) {
 
403
        if (sp != NULL)
 
404
                sp->enabled = 1;
 
405
        return;
 
406
}
 
407
 
 
408
/*
 
409
 * Check whether a sound clip is enabled.
 
410
 */
 
411
int sfxIsEnabled(Sfx sp) {
 
412
        return (sp != NULL) && sp->enabled;
 
413
}
 
414
 
 
415
/*
 
416
 * Set the volume to a specified level.
 
417
 */
 
418
void sfxSetVolume(int level) {
 
419
        if (level >= 0 && level < sizeof( gainSettings ) / sizeof( gainSettings[0])) {
 
420
                gainIndex = level;
 
421
                currLeftGain = currRightGain = gainSettings[gainIndex];
 
422
        }
 
423
        return;
 
424
}
 
425
 
 
426
/*
 
427
 * Clean up sound routines.
 
428
 */
 
429
void sfxEnd(int waitForSounds) {
 
430
        int idx;
 
431
 
 
432
        endingOnPurpose = 1;
 
433
 
 
434
        if (waitForSounds) {            /* wait for sounds to complete */
 
435
                for (idx=0; idx < nAudioPorts; idx++) {
 
436
                        while (ALgetfilled(audioPort[idx]) > 0)
 
437
                                sginap(1);
 
438
 
 
439
                        ALcloseport(audioPort[idx]);
 
440
                }
 
441
        } else if (soundChild > 0)      /* kill childs playing sounds */
 
442
                kill(soundChild, SIGKILL);
 
443
 
 
444
        if (nAudioPorts > 0)            /* reset audio subsystem */
 
445
                sfxResetAudioHw();
 
446
}
 
447
 
 
448
/*
 
449
 * Open up the audio ports.
 
450
 */
 
451
static int sfxOpenAudioPorts(ALport ports[], int maxAudioPorts) {
 
452
        int n;
 
453
 
 
454
        if (sfxCheckForAudio() == 0)
 
455
                return -1;
 
456
 
 
457
        for (n=0; n < maxAudioPorts; n++)
 
458
                if ((audioPort[n] = sfxInitAudioPort(n == 0)) == NULL)
 
459
                        break;
 
460
        return n;
 
461
}
 
462
 
 
463
/*
 
464
 * Check for audio hardware.
 
465
 */
 
466
static int sfxCheckForAudio(void) {
 
467
        int st = 0;
 
468
        inventory_t *base;
 
469
        inventory_t *inv;
 
470
 
 
471
        inv = base = getinvent();
 
472
        while (inv != NULL) {
 
473
                /*
 
474
                 * Ok if any type of audio hardware available.
 
475
                 */
 
476
                if (inv->inv_class == INV_AUDIO)
 
477
                        st = 1;
 
478
 
 
479
                inv = getinvent();
 
480
        }
 
481
        if( base )
 
482
                endinvent();
 
483
 
 
484
        return st;
 
485
}
 
486
 
 
487
/*
 
488
 * Open and initialize an audio port.
 
489
 */
 
490
static ALport sfxInitAudioPort(int init) {
 
491
        ALport ap;
 
492
        ALconfig audioPortConfig;
 
493
        long pvbuf[6];
 
494
 
 
495
        if (init) {
 
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);
 
504
        }
 
505
 
 
506
        /*
 
507
         * Configure and open audio port.
 
508
         */
 
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);
 
515
 
 
516
        return ap;
 
517
}
 
518
 
 
519
/*
 
520
 * Reset the audio hardware to where we found it when we started.
 
521
 */
 
522
static void sfxResetAudioHw(void) {
 
523
        long pvbuf[6];
 
524
 
 
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;
 
531
 
 
532
        ALsetparams(AL_DEFAULT_DEVICE, pvbuf, 6L);
 
533
        return;
 
534
}
 
535
 
 
536
/*
 
537
 * Free the Sfx structure.
 
538
 */
 
539
void sfxFree(Sfx sp) {
 
540
        if (sp) {
 
541
                if (sp->soundData) {
 
542
                        free(sp->soundData);
 
543
                        sp->soundData = NULL;
 
544
                }
 
545
                if (sp->soundSize) {
 
546
                        free(sp->soundSize);
 
547
                        sp->soundSize = NULL;
 
548
                }
 
549
                free(sp);
 
550
        }
 
551
        return;
 
552
}
 
553
 
 
554
/*
 
555
 * Set the gain index.
 
556
 */
 
557
static void sfxSetGainIndex(unsigned long gain) {
 
558
        int idx;
 
559
        long min = 256;
 
560
        long diff;
 
561
 
 
562
        for (idx=0; idx < sizeof(gainSettings) / sizeof(gainSettings[0]); idx++) {
 
563
                diff = gain - gainSettings[idx];
 
564
                if (diff < 0)
 
565
                        diff = -diff;
 
566
 
 
567
                if (diff < min) {
 
568
                        min = diff;
 
569
                        gainIndex = idx;
 
570
                }
 
571
        }
 
572
        return;
 
573
}
 
574
 
 
575
/*
 
576
 * Set the volume level.
 
577
 */
 
578
static void sfxSetGain(float l, float r) {
 
579
        long pvbuf[4];
 
580
 
 
581
        pvbuf[0] = AL_LEFT_SPEAKER_GAIN;
 
582
        pvbuf[1] = l * currLeftGain;
 
583
        pvbuf[2] = AL_RIGHT_SPEAKER_GAIN;
 
584
        pvbuf[3] = r * currRightGain;
 
585
 
 
586
        ALsetparams(AL_DEFAULT_DEVICE, pvbuf, 4L);
 
587
}
 
588
 
 
589
/*
 
590
 * Check for external volume changes.
 
591
 */
 
592
static void sfxCheckVolume(void) {
 
593
        long pvbuf[6];
 
594
 
 
595
        /*
 
596
         * Check to see if the volume was changed externally.
 
597
         */
 
598
        pvbuf[0] = AL_LEFT_SPEAKER_GAIN;
 
599
        pvbuf[2] = AL_RIGHT_SPEAKER_GAIN;
 
600
 
 
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);
 
606
        }
 
607
        return;
 
608
}
 
609
 
 
610
/*
 
611
 * Adjust the volume.
 
612
 */
 
613
int sfxVolumeChange(int direction) {
 
614
        if (sound_init) {
 
615
                sfxCheckVolume();
 
616
                if (direction == 1) {
 
617
                        if (gainIndex < sizeof(gainSettings)/sizeof(gainSettings[0])-1)
 
618
                                gainIndex++;
 
619
 
 
620
                } else if (gainIndex > 0)
 
621
                        gainIndex--;
 
622
 
 
623
                currLeftGain = currRightGain = gainSettings[gainIndex];
 
624
                sfxSetGain(1., 1.);
 
625
 
 
626
                return gainIndex;
 
627
        }
 
628
        return 0;
 
629
}
 
630
 
 
631
/*
 
632
 * Wake up the sound handler.
 
633
 */
 
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));
 
637
 
 
638
        return;
 
639
}
 
640
 
 
641
/*
 
642
 * Audio library error handler.
 
643
 */
 
644
static void sfxSoundErrFunc(long err, const char *msg, ...) { }
 
645
 
 
646
/*
 
647
 * Handler for sound child dying.
 
648
 */
 
649
static void sfxSoundDied(int sig) {
 
650
        if (!endingOnPurpose) {
 
651
                nAudioPorts = 0;
 
652
                sound_init = 0;
 
653
 
 
654
                (void) fprintf(stderr,
 
655
                                "Sound handling child process was killed by signal %d\n", sig);
 
656
        }
 
657
        return;
 
658
}
 
659
 
 
660
/*
 
661
 * Exit sound handler on SIGHUP.
 
662
 */
 
663
static void sfxDieGracefully(int sig) {
 
664
        exit(0);
 
665
}
 
666
 
 
667
/*
 
668
 * Sound handler.
 
669
 */
 
670
static void sfxSoundHandler(void *arg) {
 
671
        ALport *ap = (ALport *)arg;
 
672
        Sample samp[MAX_AUDIO_PORTS];
 
673
 
 
674
        int idx, nap;
 
675
        int treated;
 
676
        int nSounds = 1;
 
677
        int nextPort = 0;
 
678
        long maxSampsPerPass;
 
679
        long sampCount;
 
680
        long pvbuf[2];
 
681
        struct _sfx ss;
 
682
        struct pollfd pf;
 
683
 
 
684
        prctl(PR_TERMCHILD, 0);
 
685
 
 
686
        (void) signal(SIGHUP, sfxDieGracefully);
 
687
 
 
688
        maxSampsPerPass = 1600;
 
689
 
 
690
        for (idx=0; idx < nAudioPorts; idx++) {
 
691
                samp[idx].id = -1;
 
692
                samp[idx].sample = NULL;
 
693
                samp[idx].sampsToPlay = 0;
 
694
                samp[idx].repeat = 0;
 
695
        }
 
696
 
 
697
        /*
 
698
         * Set sample rate for output device.
 
699
         */
 
700
        pvbuf[0] = AL_OUTPUT_RATE;
 
701
        pvbuf[1] = AL_RATE_16000;
 
702
 
 
703
        (void) ALsetparams(AL_DEFAULT_DEVICE, pvbuf, 2L);
 
704
 
 
705
        /*
 
706
         * Prepare to read from pipe.
 
707
         */
 
708
        pf.fd = spigot[0];
 
709
        pf.events = POLLIN | POLLRDNORM | POLLRDBAND;
 
710
 
 
711
#define EVER ;;
 
712
        for (EVER) {
 
713
                if (nSounds == 0 || (idx=poll(&pf, 1, 0)) > 0) {
 
714
                        (void) read(spigot[0], &ss, sizeof(ss));
 
715
                        treated = 0;
 
716
                        if (ss.loop == 1 && ss.repeat == 0) {
 
717
                                treated = 1;
 
718
                                for (idx=0; idx < nAudioPorts; idx++) {
 
719
                                        if (samp[idx].id == ss.id) {
 
720
                                                samp[idx].id = -1;
 
721
                                                samp[idx].repeat = 0;
 
722
                                                samp[idx].sampsToPlay = 0;
 
723
                                                samp[idx].sample = NULL;
 
724
                                        }
 
725
                                }
 
726
                        } else if (ss.loop == 1 && ss.count > 1) {
 
727
                                for (idx=0; idx < nAudioPorts; idx++) {
 
728
                                        if (samp[idx].id == ss.id) {
 
729
                                                treated = 1;
 
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];
 
734
                                        }
 
735
                                }
 
736
                        }
 
737
                        if (!treated) {
 
738
                                for (idx=0; idx < nAudioPorts; idx++) {
 
739
                                        nextPort = (nextPort+1) % nAudioPorts;
 
740
                                        if (samp[nextPort].repeat == 0)
 
741
                                                break;
 
742
                                }
 
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;
 
748
                        }
 
749
                } else if (idx < 0)
 
750
                        (void) fprintf(stderr, "panic: input poll failed: %s\n", strerror(errno));
 
751
 
 
752
                nSounds = 0;
 
753
                nap = 0;
 
754
 
 
755
                for (idx=0; idx < nAudioPorts; idx++) {
 
756
                        if (samp[idx].sampsToPlay > 0) {
 
757
                                nSounds++;
 
758
                                if (ALgetfilled(ap[idx]) > 4000) {
 
759
                                        nap++;
 
760
                                        continue;
 
761
                                }
 
762
                        }
 
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;
 
768
 
 
769
                        } else if (samp[idx].sampsToPlay > 0) {
 
770
                                if ((samp[idx].sampsToPlay%2) == 1) {
 
771
                                        samp[idx].sampsToPlay -= 1;
 
772
                                        samp[idx].sampsPlayed += 1;
 
773
                                }
 
774
                                if (samp[idx].sampsToPlay > 0)
 
775
                                    (void) ALwritesamps(ap[idx],
 
776
                                                        samp[idx].sample+samp[idx].sampsPlayed, samp[idx].sampsToPlay);
 
777
 
 
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);
 
783
                                } else
 
784
                                        samp[idx].sampsToPlay = 0;
 
785
                        }
 
786
                }
 
787
                if (nap == nSounds)
 
788
                        sginap(1);
 
789
        }
 
790
        return;
 
791
}
 
792
 
 
793
/*
 
794
 * Open an audio file, check for recognized type, and read.
 
795
 */
 
796
static short *sfxLoadAudioFile(char *dirName, char *fileName, AFframecount *size) {
 
797
        int fd;
 
798
        int sampleWidth;
 
799
        int sampleFmt;
 
800
        char *name;
 
801
        short *data;
 
802
        AFfilehandle file;
 
803
 
 
804
        if (!(name = malloc(strlen(dirName)+strlen(fileName)+2)))
 
805
                return NULL;
 
806
 
 
807
        (void) sprintf(name, "%s/%s", dirName, fileName);
 
808
 
 
809
        if ((fd=open(name, O_RDONLY)) < 0) {
 
810
                (void) fprintf(stderr, "Could not open audio file `%s': %s\n", name, strerror(errno));
 
811
                free(name);
 
812
                return NULL;
 
813
        }
 
814
 
 
815
        switch(AFidentifyfd(fd)) {
 
816
          case AF_FILE_AIFF:
 
817
          case AF_FILE_AIFFC:
 
818
                break;
 
819
 
 
820
          default:
 
821
                (void) fprintf(stderr, "%s: unrecognized file type -- convert to AIFF or AIFC\n", name);
 
822
                free(name);
 
823
                return NULL;
 
824
        }
 
825
        file = AFopenfd(fd, "r", AF_NULL_FILESETUP);
 
826
 
 
827
        if (file == AF_NULL_FILEHANDLE) {
 
828
                fprintf(stderr, "%s: failed to attach an audio file struct\n", name);
 
829
                free(name);
 
830
                return NULL;
 
831
        }
 
832
 
 
833
        if ((int)AFgetchannels(file, AF_DEFAULT_TRACK) != 2) {
 
834
                fprintf(stderr, "%s: does not have 2 channels\n", name);
 
835
                free(name);
 
836
                AFclosefile(file);
 
837
                return NULL;
 
838
        }
 
839
 
 
840
        if (AFgetrate(file, AF_DEFAULT_TRACK) != 16000) {
 
841
                fprintf(stderr, "%s: is not recorded at 16 KHz\n", name);
 
842
                free(name);
 
843
                AFclosefile(file);
 
844
                return NULL;
 
845
        }
 
846
 
 
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);
 
850
                free(name);
 
851
                AFclosefile(file);
 
852
                return NULL;
 
853
        }
 
854
        free(name);
 
855
 
 
856
        *size = AFgetframecnt(file, AF_DEFAULT_TRACK);
 
857
 
 
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);
 
860
                *size = 0;
 
861
                AFclosefile(file);
 
862
                return NULL;
 
863
        }
 
864
 
 
865
        if (AFreadframes(file, AF_DEFAULT_TRACK, data, (int)*size) != (int)*size) {
 
866
                (void) fprintf(stderr, "%s: error reading\n", name);
 
867
                free(data);
 
868
                data = NULL;
 
869
                *size = 0L;
 
870
        }
 
871
 
 
872
        *size *= 2L;
 
873
        AFclosefile(file);
 
874
        return data;
 
875
}
 
876
 
 
877
#elif defined(HAVE_SDL)
 
878
/*
 
879
 * Build the path to the sound files 
 
880
 */
 
881
static char *DATAFILE(const char* wav) {
 
882
        static char buf[PATH_MAX];
 
883
 
 
884
        (void) snprintf(buf, sizeof buf, "%s/%s", sounddir, wav);
 
885
        return (char *)buf;
 
886
 
887
 
 
888
/*
 
889
 * Load the .wave files into the sounds array
 
890
 */
 
891
static int loadSounds(void) {
 
892
        int i;
 
893
 
 
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"));
 
912
 
 
913
        for (i=0; i < NUM_WAVES; i++) {
 
914
                if (!sounds[i]) {
 
915
                        (void) fprintf(stderr, "Mix_LoadWAV sound[%d] could not be loaded."
 
916
                                                "Check soundDir in your .netrekrc: %s\n", i, Mix_GetError());
 
917
                        return -1;
 
918
                }
 
919
        }
 
920
        return 1;
 
921
}
 
922
 
 
923
void sound_cleanup (void) {
 
924
        int i;
 
925
 
 
926
        /* Free the sound effects */
 
927
        for (i = 0; i < NUM_WAVES; i++)
 
928
                Mix_FreeChunk(sounds[i]);
 
929
 
 
930
        /* Quit SDL_mixer */
 
931
        Mix_CloseAudio();
 
932
 
 
933
        /* Quit SDL */  /* Oh boy, what a meaningful comment! */
 
934
        SDL_Quit();
 
935
}
 
936
#endif /* HAVE_SDL */
 
937
 
 
938
void Exit_Sound(void) {
 
939
 
 
940
#if defined(sgi)
 
941
        if (sound_init)
 
942
                sfxEnd(1);
 
943
 
 
944
#elif !defined(HAVE_SDL)
 
945
        if (sound_init)
 
946
                ExitSound();
 
947
#endif
 
948
        sound_init = 0;
 
949
        sound_toggle = 0;
 
950
}
 
951
 
 
952
void Init_Sound(void) {
 
953
        char *sd;
 
954
 
 
955
#if defined(sgi)
 
956
        int err;
 
957
#else
 
958
        char buf[PATH_MAX];
 
959
#endif
 
960
 
 
961
#ifdef DEBUG
 
962
        printf("Init_Sound\n");
 
963
#endif
 
964
        /*
 
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.
 
969
         */
 
970
        if (sound_init) {
 
971
                if ((sounddir = getdefault("sounddir")) == NULL) {
 
972
                        if ((sd=getenv("SOUNDDIR")) != NULL)
 
973
                                sounddir = strdup(sd);
 
974
                        else
 
975
                                sounddir = "/usr/local/games/netrek-sgi/sounds";
 
976
                }
 
977
                if (!isDirectory(sounddir)) {
 
978
                        (void) fprintf(stderr, "%s is not a directory, sound will not work\n", sounddir);
 
979
        }
 
980
#if defined(sgi)
 
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");
 
984
                sound_init = 0;
 
985
                sound_toggle = 0;
 
986
                return;
 
987
        }
 
988
        if (err == SFX_ERR_NO_SPROC) {
 
989
                (void) fprintf(stderr, "Unable to execute sound process.\n");
 
990
                sound_init = 0;
 
991
                sound_toggle = 0;
 
992
                return;
 
993
        }
 
994
        if (err == SFX_ERR_NO_MEM) {
 
995
                (void) fprintf(stderr, "No memory available for sound data.\n");
 
996
                sound_init = 0;
 
997
                sound_toggle = 0;
 
998
                return;
 
999
        }
 
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");
 
1011
 
 
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");
 
1020
 
 
1021
                        /* load sound loops only if we got three audio ports */
 
1022
                        if (err > 2) {
 
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");
 
1026
 
 
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);
 
1030
                                }
 
1031
                        }
 
1032
                }
 
1033
                sfxPlay(sounds[INTRO_WAV]);
 
1034
        }
 
1035
 
 
1036
#elif defined(HAVE_SDL)
 
1037
#ifdef DEBUG
 
1038
        printf("Init_Sound using SDL\n");
 
1039
#endif
 
1040
 
 
1041
    /* Initialize the SDL library */
 
1042
    if (SDL_Init(SDL_INIT_AUDIO) < 0) {
 
1043
      fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError());
 
1044
    }
 
1045
    atexit(SDL_Quit);
 
1046
 
 
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());
 
1050
      sound_init = 0;
 
1051
    } 
 
1052
 
 
1053
    /* If we successfully loaded the wav files, so shut-off sound_init and play
 
1054
     * the introduction
 
1055
     */
 
1056
    if (loadSounds()) {
 
1057
      if (Mix_PlayChannel(-1, sounds[INTRO_WAV], 0) < 0) {
 
1058
        fprintf(stderr, "Mix_PlayChannel: %s\n", Mix_GetError());
 
1059
      }
 
1060
    }
 
1061
#else
 
1062
    if (InitSound() == -1) {
 
1063
      sound_toggle = 0;
 
1064
      sound_init = 0;
 
1065
    } else {
 
1066
      sound_init = 1;
 
1067
      sound_toggle = 1;
 
1068
    }
 
1069
 
 
1070
    strcpy(sound_prefix, sounddir);
 
1071
    strcat(sound_prefix, "/");
 
1072
 
 
1073
    if (sound_toggle) {
 
1074
    strcpy(buf, sounddir);
 
1075
    strcat(buf, "/nt_intro");
 
1076
    StartSound(buf);
 
1077
    }
 
1078
#endif
 
1079
  }
 
1080
}
 
1081
 
 
1082
#if defined(HAVE_SDL) || defined(sgi)
 
1083
static int sound2wave[NUM_SOUNDS+1] = {
 
1084
        /* NO_SOUND */                  -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,
 
1097
#if defined(sgi)
 
1098
        /* ENGINE_SOUND */              ENGINE_WAV,
 
1099
#else
 
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,
 
1103
#endif
 
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
 
1123
};
 
1124
#endif
 
1125
 
 
1126
#if defined(HAVE_SDL) || defined(sgi)
 
1127
static int get_waveform(int type) {
 
1128
        int waveform;
 
1129
 
 
1130
        if (type <= 0 || type > NUM_SOUNDS) {                   /* check sound index */
 
1131
#ifdef DEBUG
 
1132
                (void) fprintf(stderr, "panic: non-existent sound number: %i\n", type);
 
1133
#endif
 
1134
                return -1;
 
1135
        }
 
1136
 
 
1137
        if ((waveform = sound2wave[type]) >= NUM_WAVES) {       /* check waveform index */
 
1138
#ifdef DEBUG
 
1139
                (void) fprintf(stderr, "panic: non-existent waveform number: %i\n", waveform);
 
1140
#endif
 
1141
                return -1;
 
1142
        }
 
1143
        return waveform;
 
1144
}
 
1145
#endif
 
1146
 
 
1147
void Play_Sound(int type) {
 
1148
#if defined(HAVE_SDL) || defined(sgi)
 
1149
        int waveform;
 
1150
 
 
1151
        if (!sound_init || (waveform=get_waveform(type)) < 0)
 
1152
                return;
 
1153
 
 
1154
#if defined(sgi)
 
1155
        if (type > OTHER_SOUND_OFFSET && !soundOther)
 
1156
                return;
 
1157
 
 
1158
        sfxPlay(sounds[waveform]);
 
1159
 
 
1160
#else
 
1161
        if (Mix_PlayChannel(-1, sounds[waveform], 0) < 0) {
 
1162
                (void) fprintf(stderr, "Mix_PlayChannel: %s\n", Mix_GetError());
 
1163
        }
 
1164
#endif
 
1165
 
 
1166
#else
 
1167
        char buf[PATH_MAX];
 
1168
 
 
1169
        /* Don't play other ship's sounds if turned off */
 
1170
        if (type > OTHER_SOUND_OFFSET && !soundOther)
 
1171
                return;
 
1172
 
 
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);
 
1177
                StartSound(buf);
 
1178
                current_sound = type;
 
1179
        }
 
1180
        if (!(sound_toggle))
 
1181
                current_sound = NO_SOUND;
 
1182
#endif
 
1183
}
 
1184
 
 
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))
 
1189
                StopSound();
 
1190
#endif
 
1191
}
 
1192
#endif
 
1193
 
 
1194
#if defined(sgi)
 
1195
/*
 
1196
 * Play a pitch-bended engine sound loop while player is alive.
 
1197
 */
 
1198
void Engine_Sound(int speed, int maxspeed) {
 
1199
        static int engine_on = 0;
 
1200
        static float opitch = 0.0f;
 
1201
        float pitch;
 
1202
 
 
1203
        if (!sound_init)
 
1204
                return;
 
1205
 
 
1206
        if ((speed < 0) && (maxspeed < 0)) {    /* stop sound */
 
1207
                sfxDisable(sounds[ENGINE_WAV]);
 
1208
                engine_on = 0;
 
1209
                opitch = 0.0f;
 
1210
                return;
 
1211
        }
 
1212
        if (speed == 0)
 
1213
                pitch = 0.0f;
 
1214
        else    pitch = 0.25f * (float)speed * (1.0f / (float)maxspeed);
 
1215
 
 
1216
        if (!engine_on || opitch != pitch) {
 
1217
                sfxEnable(sounds[ENGINE_WAV]);
 
1218
                sfxPlayPitch(sounds[ENGINE_WAV], pitch);
 
1219
                engine_on = 1;
 
1220
                opitch = pitch;
 
1221
        }
 
1222
        return;
 
1223
}
 
1224
#endif
 
1225
 
 
1226
/* Sound options window stuff */
 
1227
 
 
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
 
1232
 
 
1233
static void soundrefresh(int i);
 
1234
 
 
1235
int sound_window_height(void) {
 
1236
#if defined(HAVE_SDL)
 
1237
        return 1;
 
1238
#else
 
1239
        return MESSAGE_SOUND + 4;
 
1240
#endif
 
1241
}
 
1242
 
 
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);
 
1247
#else
 
1248
        int     i;
 
1249
 
 
1250
        for (i=0; i <= SOUND_DONE; i++)
 
1251
                soundrefresh(i);
 
1252
#endif
 
1253
 
 
1254
        /* Map window */
 
1255
        W_MapWindow(soundWin);
 
1256
}
 
1257
 
 
1258
#if !defined(HAVE_SDL)
 
1259
static void soundrefresh(int i) {
 
1260
        char buf[200], *flag;
 
1261
 
 
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) {
 
1265
#if defined(sgi)
 
1266
                flag = (sfxIsEnabled(sounds[i]) ? "ON" : "OFF");
 
1267
#else
 
1268
                flag = ((sounds[i].flag == 1) ? "ON" : "OFF");
 
1269
#endif
 
1270
                switch (i) {
 
1271
                  case FIRE_TORP_SOUND:
 
1272
                        (void) snprintf(buf, sizeof buf, "Fire torp sound is %s", flag);
 
1273
                        break;
 
1274
 
 
1275
                  case PHASER_SOUND:
 
1276
                        (void) snprintf(buf, sizeof buf, "Phaser sound is %s", flag);
 
1277
                        break;
 
1278
 
 
1279
                  case FIRE_PLASMA_SOUND:
 
1280
                        (void) snprintf(buf, sizeof buf, "Fire plasma sound is %s", flag);
 
1281
                        break;
 
1282
 
 
1283
                  case EXPLOSION_SOUND:
 
1284
                        (void) snprintf(buf, sizeof buf, "Explosion sound is %s", flag);
 
1285
                        break;
 
1286
 
 
1287
                  case CLOAK_SOUND:
 
1288
                        (void) snprintf(buf, sizeof buf, "Cloak sound is %s", flag);
 
1289
                        break;
 
1290
 
 
1291
                  case UNCLOAK_SOUND:
 
1292
                        (void) snprintf(buf, sizeof buf, "Uncloak sound is %s", flag);
 
1293
                        break;
 
1294
 
 
1295
                  case SHIELD_DOWN_SOUND:
 
1296
                        (void) snprintf(buf, sizeof buf, "Shield down  sound is %s", flag);
 
1297
                        break;
 
1298
 
 
1299
                  case SHIELD_UP_SOUND:
 
1300
                        (void) snprintf(buf, sizeof buf, "Shield up sound is %s", flag);
 
1301
                        break;
 
1302
 
 
1303
                  case TORP_HIT_SOUND:
 
1304
                        (void) snprintf(buf, sizeof buf, "Torp hit sound is %s", flag);
 
1305
                        break;
 
1306
 
 
1307
                  case REDALERT_SOUND:
 
1308
                        (void) snprintf(buf, sizeof buf, "Red alert sound is %s", flag);
 
1309
                        break;
 
1310
 
 
1311
                  case ENGINE_SOUND:
 
1312
#if defined(sgi)
 
1313
                        (void) snprintf(buf, sizeof buf, "Engine sound is %s", flag);
 
1314
#else
 
1315
                        (void) snprintf(buf, sizeof buf, "Engine sound is not supported");
 
1316
#endif
 
1317
                        break;
 
1318
 
 
1319
                  case ENTER_SHIP_SOUND:
 
1320
                        (void) snprintf(buf, sizeof buf, "Enter ship sound is %s", flag);
 
1321
                        break;
 
1322
 
 
1323
                  case SELF_DESTRUCT_SOUND:
 
1324
                        (void) snprintf(buf, sizeof buf, "Self destruct sound is %s", flag);
 
1325
                        break;
 
1326
 
 
1327
                  case PLASMA_HIT_SOUND:
 
1328
                        (void) snprintf(buf, sizeof buf, "Plasma hit sound is %s", flag);
 
1329
                        break;
 
1330
 
 
1331
                  case MESSAGE_SOUND:
 
1332
                        (void) snprintf(buf, sizeof buf, "Message sound is %s", flag);
 
1333
                        break;
 
1334
                }
 
1335
 
 
1336
        } else if (i == SOUND_OTHER)
 
1337
                (void) snprintf(buf, sizeof buf, "Other ship's sound is %s", soundOther == 1 ? "ON" : "OFF");
 
1338
#if defined(sgi)
 
1339
        else if (i == SOUND_INIT)
 
1340
                (void) snprintf(buf, sizeof buf, sound_init ? "Reset audio hardware"
 
1341
                                                           : "Initialize audio hardware");
 
1342
#else
 
1343
        else if (i == SOUND_INIT)
 
1344
                (void) snprintf(buf, sizeof buf, sound_init ? "Restart external sound player"
 
1345
                                                           : "Initialize external sound player");
 
1346
#endif
 
1347
        else if (i == SOUND_DONE)
 
1348
                (void) snprintf(buf, sizeof buf, "Done");
 
1349
        else
 
1350
                (void) fprintf(stderr, "Uh oh, bogus refresh number in soundrefresh\n");
 
1351
 
 
1352
        W_WriteText(soundWin, 0, i, textColor, buf, strlen(buf), 0);
 
1353
}
 
1354
#endif /* HAVE_SDL */
 
1355
 
 
1356
void soundaction(W_Event * data) {
 
1357
#if defined(sgi)
 
1358
        printf("sorry, not yet implemented\n");
 
1359
 
 
1360
#elif !defined(HAVE_SDL)
 
1361
  int     i, j;
 
1362
 
 
1363
  i = data->y;
 
1364
 
 
1365
  if (i == SOUND_TOGGLE) {
 
1366
      if (sound_init)
 
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);
 
1372
      } else {
 
1373
          Play_Sound(ENGINE_SOUND);
 
1374
      }
 
1375
      */
 
1376
    }
 
1377
  else if (i < SOUND_OTHER)
 
1378
    {
 
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;
 
1382
 
 
1383
      soundrefresh(i);
 
1384
      Play_Sound(i);
 
1385
      if (i == MESSAGE_SOUND)
 
1386
        {
 
1387
          for (j = MESSAGE1_SOUND; j <= MESSAGE9_SOUND; j++)
 
1388
            sounds[j].flag = sounds[MESSAGE_SOUND].flag;
 
1389
        }
 
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; */
 
1393
 
 
1394
    }
 
1395
  else if (i == SOUND_OTHER)
 
1396
    {
 
1397
      soundOther = !soundOther;
 
1398
      soundrefresh(SOUND_OTHER);
 
1399
    }
 
1400
  else if (i == SOUND_INIT)
 
1401
    {
 
1402
      Exit_Sound();
 
1403
      sound_init = 1;
 
1404
      Init_Sound();
 
1405
      soundrefresh(SOUND_INIT);
 
1406
      soundrefresh(SOUND_TOGGLE);
 
1407
    }
 
1408
  else
 
1409
    {
 
1410
      sounddone();
 
1411
    }
 
1412
#endif /* HAVE_SDL */
 
1413
}
 
1414
 
 
1415
void sounddone(void) {
 
1416
 
 
1417
        W_UnmapWindow(soundWin);
 
1418
        return;
 
1419
}
 
1420
 
 
1421
#endif /* SOUND */