Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
298 | serge | 1 | // Emacs style mode select -*- C++ -*- |
2 | //----------------------------------------------------------------------------- |
||
3 | // |
||
4 | // $Id:$ |
||
5 | // |
||
6 | // Copyright (C) 1993-1996 by id Software, Inc. |
||
7 | // |
||
8 | // This source is available for distribution and/or modification |
||
9 | // only under the terms of the DOOM Source Code License as |
||
10 | // published by id Software. All rights reserved. |
||
11 | // |
||
12 | // The source is distributed in the hope that it will be useful, |
||
13 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
14 | // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License |
||
15 | // for more details. |
||
16 | // |
||
17 | // $Log:$ |
||
18 | // |
||
19 | // DESCRIPTION: |
||
20 | // System interface for sound. |
||
21 | // |
||
22 | //----------------------------------------------------------------------------- |
||
23 | |||
24 | static const char |
||
25 | rcsid[] = "$Id: i_unix.c,v 1.5 1997/02/03 22:45:10 b1 Exp $"; |
||
26 | |||
27 | #include |
||
28 | #include |
||
29 | #include |
||
30 | |||
31 | #include |
||
32 | |||
33 | #include |
||
34 | #include |
||
35 | |||
36 | //#ifndef LINUX |
||
37 | //#include |
||
38 | //#endif |
||
39 | |||
40 | #include |
||
41 | #include |
||
42 | //#include |
||
43 | //#include |
||
44 | |||
45 | // Linux voxware output. |
||
46 | //#include |
||
47 | |||
48 | // Timer stuff. Experimental. |
||
49 | #include |
||
50 | #include |
||
51 | |||
52 | #include "z_zone.h" |
||
53 | |||
54 | #include "i_system.h" |
||
55 | #include "i_sound.h" |
||
56 | #include "m_argv.h" |
||
57 | #include "m_misc.h" |
||
58 | #include "w_wad.h" |
||
59 | |||
60 | #include "doomdef.h" |
||
61 | |||
62 | typedef unsigned int DWORD; |
||
63 | |||
64 | //////////////////////////////////////////////////////////////////////////// |
||
65 | // WinDoom - DirectSound |
||
66 | //////////////////////////////////////////////////////////////////////////// |
||
67 | |||
68 | #define NUM_SOUND_FX 128 |
||
69 | #define SB_SIZE 20480 |
||
70 | |||
71 | void CreateSoundBuffer(int Channel, int length, unsigned char *data); |
||
72 | void I_PlaySoundEffect(int sfxid, int Channel, int volume, int pan); |
||
73 | |||
74 | #define NUM_DSBUFFERS 256 |
||
75 | |||
76 | typedef enum { dsb_perm, dsb_temp } dsb_type; |
||
77 | |||
78 | typedef struct |
||
79 | { |
||
80 | void *origin; |
||
81 | int dsb_type; |
||
82 | int sfxid; |
||
83 | }DSBControl_t; |
||
84 | |||
85 | DSBControl_t DSBControl[NUM_DSBUFFERS]; |
||
86 | |||
87 | extern int swap_stereo; |
||
88 | |||
89 | //////////////////////////////////////////////////////////////////////////// |
||
90 | |||
91 | // UNIX hack, to be removed. |
||
92 | #ifdef SNDSERV |
||
93 | // Separate sound server process. |
||
94 | FILE* sndserver=0; |
||
95 | char* sndserver_filename = "./sndserver "; |
||
96 | #elif SNDINTR |
||
97 | |||
98 | // Update all 30 millisecs, approx. 30fps synchronized. |
||
99 | // Linux resolution is allegedly 10 millisecs, |
||
100 | // scale is microseconds. |
||
101 | #define SOUND_INTERVAL 500 |
||
102 | |||
103 | // Get the interrupt. Set duration in millisecs. |
||
104 | int I_SoundSetTimer( int duration_of_tick ); |
||
105 | void I_SoundDelTimer( void ); |
||
106 | #else |
||
107 | // None? |
||
108 | #endif |
||
109 | |||
110 | |||
111 | // A quick hack to establish a protocol between |
||
112 | // synchronous mix buffer updates and asynchronous |
||
113 | // audio writes. Probably redundant with gametic. |
||
114 | static int flag = 0; |
||
115 | |||
116 | // The number of internal mixing channels, |
||
117 | // the samples calculated for each mixing step, |
||
118 | // the size of the 16bit, 2 hardware channel (stereo) |
||
119 | // mixing buffer, and the samplerate of the raw data. |
||
120 | |||
121 | |||
122 | // Needed for calling the actual sound output. |
||
123 | #define SAMPLECOUNT 512 |
||
124 | #define NUM_CHANNELS 16 |
||
125 | // It is 2 for 16bit, and 2 for two channels. |
||
126 | #define BUFMUL 4 |
||
127 | #define MIXBUFFERSIZE (SAMPLECOUNT*BUFMUL) |
||
128 | |||
129 | #define SAMPLERATE 11025 // Hz |
||
130 | #define SAMPLESIZE 2 // 16bit |
||
131 | |||
132 | // The actual lengths of all sound effects. |
||
133 | int lengths[NUMSFX]; |
||
134 | |||
135 | // The actual output device. |
||
136 | //int audio_fd; |
||
137 | |||
138 | // The global mixing buffer. |
||
139 | // Basically, samples from all active internal channels |
||
140 | // are modifed and added, and stored in the buffer |
||
141 | // that is submitted to the audio device. |
||
142 | signed short mixbuffer[MIXBUFFERSIZE]; |
||
143 | |||
144 | |||
145 | // The channel step amount... |
||
146 | unsigned int channelstep[NUM_CHANNELS]; |
||
147 | // ... and a 0.16 bit remainder of last step. |
||
148 | unsigned int channelstepremainder[NUM_CHANNELS]; |
||
149 | |||
150 | |||
151 | // The channel data pointers, start and end. |
||
152 | unsigned char* channels[NUM_CHANNELS]; |
||
153 | unsigned char* channelsend[NUM_CHANNELS]; |
||
154 | |||
155 | |||
156 | // Time/gametic that the channel started playing, |
||
157 | // used to determine oldest, which automatically |
||
158 | // has lowest priority. |
||
159 | // In case number of active sounds exceeds |
||
160 | // available channels. |
||
161 | int channelstart[NUM_CHANNELS]; |
||
162 | |||
163 | // The sound in channel handles, |
||
164 | // determined on registration, |
||
165 | // might be used to unregister/stop/modify, |
||
166 | // currently unused. |
||
167 | int channelhandles[NUM_CHANNELS]; |
||
168 | |||
169 | // SFX id of the playing sound effect. |
||
170 | // Used to catch duplicates (like chainsaw). |
||
171 | int channelids[NUM_DSBUFFERS]; |
||
172 | |||
173 | // Pitch to stepping lookup, unused. |
||
174 | int steptable[256]; |
||
175 | |||
176 | // Volume lookups. |
||
177 | int vol_lookup[128*256]; |
||
178 | |||
179 | // Hardware left and right channel volume lookup. |
||
180 | int* channelleftvol_lookup[NUM_CHANNELS]; |
||
181 | int* channelrightvol_lookup[NUM_CHANNELS]; |
||
182 | |||
183 | |||
184 | // |
||
185 | // Safe ioctl, convenience. |
||
186 | // |
||
187 | void |
||
188 | myioctl |
||
189 | ( int fd, |
||
190 | int command, |
||
191 | int* arg ) |
||
192 | { |
||
193 | // FIXME |
||
194 | /* |
||
195 | int rc; |
||
196 | extern int errno; |
||
197 | |||
198 | rc = ioctl(fd, command, arg); |
||
199 | if (rc < 0) |
||
200 | { |
||
201 | fprintf(stderr, "ioctl(dsp,%d,arg) failed\n", command); |
||
202 | fprintf(stderr, "errno=%d\n", errno); |
||
203 | exit(-1); |
||
204 | } |
||
205 | */ |
||
206 | } |
||
207 | |||
208 | |||
209 | |||
210 | |||
211 | |||
212 | // |
||
213 | // This function loads the sound data from the WAD lump, |
||
214 | // for single sound. |
||
215 | // |
||
216 | void *getsfx( char *sfxname, int *len ) |
||
217 | { |
||
218 | unsigned char* sfx; |
||
219 | unsigned char* paddedsfx; |
||
220 | int i; |
||
221 | int size; |
||
222 | int paddedsize; |
||
223 | char name[20]; |
||
224 | int sfxlump; |
||
225 | |||
226 | |||
227 | sprintf(name, "ds%s", sfxname); |
||
228 | |||
229 | // Get the sound data from the WAD, allocate lump |
||
230 | // in zone memory. |
||
231 | // Now, there is a severe problem with the |
||
232 | // sound handling, in it is not (yet/anymore) |
||
233 | // gamemode aware. That means, sounds from |
||
234 | // DOOM II will be requested even with DOOM |
||
235 | // shareware. |
||
236 | // The sound list is wired into sounds.c, |
||
237 | // which sets the external variable. |
||
238 | // I do not do runtime patches to that |
||
239 | // variable. Instead, we will use a |
||
240 | // default sound for replacement. |
||
241 | |||
242 | if ( W_CheckNumForName(name) == -1 ) |
||
243 | sfxlump = W_GetNumForName("dspistol"); |
||
244 | else |
||
245 | sfxlump = W_GetNumForName(name); |
||
246 | |||
247 | size = W_LumpLength( sfxlump ); |
||
248 | |||
249 | // sprintf(MsgText, "Getting sound effect : %s - %d\n", name, size); |
||
250 | // WriteDebug(MsgText); |
||
251 | |||
252 | // Debug. |
||
253 | // fprintf( stderr, "." ); |
||
254 | //fprintf( stderr, " -loading %s (lump %d, %d bytes)\n", |
||
255 | // sfxname, sfxlump, size ); |
||
256 | //fflush( stderr ); |
||
257 | |||
258 | sfx = (unsigned char*)W_CacheLumpNum( sfxlump, PU_STATIC ); |
||
259 | |||
260 | // Pads the sound effect out to the mixing buffer size. |
||
261 | // The original realloc would interfere with zone memory. |
||
262 | paddedsize = ((size-8 + (SAMPLECOUNT-1)) / SAMPLECOUNT) * SAMPLECOUNT; |
||
263 | |||
264 | // Allocate from zone memory. |
||
265 | paddedsfx = (unsigned char*)Z_Malloc( paddedsize+8, PU_STATIC, 0 ); |
||
266 | // ddt: (unsigned char *) realloc(sfx, paddedsize+8); |
||
267 | // This should interfere with zone memory handling, |
||
268 | // which does not kick in in the soundserver. |
||
269 | |||
270 | // Now copy and pad. |
||
271 | memcpy( paddedsfx, sfx, size ); |
||
272 | for (i = size; i < paddedsize+8; i++) |
||
273 | paddedsfx[i] = 128; |
||
274 | |||
275 | // Remove the cached lump. |
||
276 | Z_Free( sfx ); |
||
277 | |||
278 | // Preserve padded length. |
||
279 | *len = paddedsize; |
||
280 | |||
281 | // Return allocated padded data. |
||
282 | return (void *) (paddedsfx + 8); |
||
283 | } |
||
284 | |||
285 | |||
286 | |||
287 | /* |
||
288 | |||
289 | // |
||
290 | // This function adds a sound to the |
||
291 | // list of currently active sounds, |
||
292 | // which is maintained as a given number |
||
293 | // (eight, usually) of internal channels. |
||
294 | // Returns a handle. |
||
295 | // |
||
296 | int addsfx( int sfxid, int volume, int step, int seperation ) |
||
297 | { |
||
298 | static unsigned short handlenums = 0; |
||
299 | |||
300 | int i; |
||
301 | int rc = -1; |
||
302 | |||
303 | int oldest = gametic; |
||
304 | int oldestnum = 0; |
||
305 | int slot; |
||
306 | |||
307 | int rightvol; |
||
308 | int leftvol; |
||
309 | |||
310 | int iVolume, iPan; |
||
311 | |||
312 | // Chainsaw troubles. |
||
313 | // Play these sound effects only one at a time. |
||
314 | if ( sfxid == sfx_sawup || sfxid == sfx_sawidl || sfxid == sfx_sawful || |
||
315 | sfxid == sfx_sawhit || sfxid == sfx_stnmov || sfxid == sfx_pistol ) |
||
316 | { |
||
317 | // Loop all channels, check. |
||
318 | for (i = 0; i < NUM_CHANNELS; i++) |
||
319 | { |
||
320 | // Active, and using the same SFX? |
||
321 | if ( (channels[i]) && (channelids[i] == sfxid) ) |
||
322 | { |
||
323 | // Reset. |
||
324 | channels[i] = 0; |
||
325 | // We are sure that iff, there will only be one. |
||
326 | break; |
||
327 | } |
||
328 | } |
||
329 | } |
||
330 | |||
331 | // Loop all channels to find oldest SFX. |
||
332 | for (i = 0; (i |
||
333 | { |
||
334 | if (channelstart[i] < oldest) |
||
335 | { |
||
336 | oldestnum = i; |
||
337 | oldest = channelstart[i]; |
||
338 | } |
||
339 | } |
||
340 | |||
341 | // Tales from the cryptic. |
||
342 | // If we found a channel, fine. |
||
343 | // If not, we simply overwrite the first one, 0. |
||
344 | // Probably only happens at startup. |
||
345 | if (i == NUM_CHANNELS) |
||
346 | slot = oldestnum; |
||
347 | else |
||
348 | slot = i; |
||
349 | |||
350 | // Okay, in the less recent channel, |
||
351 | // we will handle the new SFX. |
||
352 | // Set pointer to raw data. |
||
353 | channels[slot] = (unsigned char *) S_sfx[sfxid].data; |
||
354 | // Set pointer to end of raw data. |
||
355 | channelsend[slot] = channels[slot] + lengths[sfxid]; |
||
356 | |||
357 | // Reset current handle number, limited to 0..100. |
||
358 | if (!handlenums) |
||
359 | handlenums = 100; |
||
360 | |||
361 | // Assign current handle number. |
||
362 | // Preserved so sounds could be stopped (unused). |
||
363 | channelhandles[slot] = rc = handlenums++; |
||
364 | |||
365 | // Set stepping??? |
||
366 | // Kinda getting the impression this is never used. |
||
367 | channelstep[slot] = step; |
||
368 | // ??? |
||
369 | channelstepremainder[slot] = 0; |
||
370 | // Should be gametic, I presume. |
||
371 | channelstart[slot] = gametic; |
||
372 | |||
373 | iVolume = 0-(128*(15-volume)); |
||
374 | if (iVolume < -10000) |
||
375 | iVolume == -10000; |
||
376 | iPan = (seperation-128)*20; |
||
377 | if (iPan < -10000) |
||
378 | iPan = -10000; |
||
379 | if (iPan > 10000) |
||
380 | iPan = 10000; |
||
381 | |||
382 | if (swap_stereo == TRUE) |
||
383 | iPan *= -1; |
||
384 | |||
385 | // Separation, that is, orientation/stereo. |
||
386 | // range is: 1 - 256 |
||
387 | |||
388 | seperation += 1; |
||
389 | |||
390 | // Per left/right channel. |
||
391 | // x^2 seperation, |
||
392 | // adjust volume properly. |
||
393 | leftvol = volume - ((volume*seperation*seperation) >> 16); //(256*256); |
||
394 | seperation = seperation - 257; |
||
395 | rightvol = volume - ((volume*seperation*seperation) >> 16); |
||
396 | |||
397 | // Sanity check, clamp volume. |
||
398 | if (rightvol < 0 || rightvol > 127) |
||
399 | I_Error("rightvol out of bounds"); |
||
400 | |||
401 | if (leftvol < 0 || leftvol > 127) |
||
402 | I_Error("leftvol out of bounds"); |
||
403 | |||
404 | // Get the proper lookup table piece |
||
405 | // for this volume level??? |
||
406 | channelleftvol_lookup[slot] = &vol_lookup[leftvol*256]; |
||
407 | channelrightvol_lookup[slot] = &vol_lookup[rightvol*256]; |
||
408 | |||
409 | // Preserve sound SFX id, |
||
410 | // e.g. for avoiding duplicates of chainsaw. |
||
411 | channelids[slot] = sfxid; |
||
412 | |||
413 | I_PlaySoundEffect(sfxid, iVolume, iPan); |
||
414 | |||
415 | // You tell me. |
||
416 | //return rc; |
||
417 | return sfxid; |
||
418 | } |
||
419 | |||
420 | */ |
||
421 | // |
||
422 | // This function adds a sound to the |
||
423 | // list of currently active sounds, |
||
424 | // which is maintained as a given number |
||
425 | // (eight, usually) of internal channels. |
||
426 | // Returns a handle. |
||
427 | // |
||
428 | |||
429 | // |
||
430 | // SFX API |
||
431 | // Note: this was called by S_Init. |
||
432 | // However, whatever they did in the |
||
433 | // old DPMS based DOS version, this |
||
434 | // were simply dummies in the Linux |
||
435 | // version. |
||
436 | // See soundserver initdata(). |
||
437 | // |
||
438 | void I_SetChannels() |
||
439 | { |
||
440 | // Init internal lookups (raw data, mixing buffer, channels). |
||
441 | // This function sets up internal lookups used during |
||
442 | // the mixing process. |
||
443 | int i; |
||
444 | int j; |
||
445 | |||
446 | int* steptablemid = steptable + 128; |
||
447 | |||
448 | // Okay, reset internal mixing channels to zero. |
||
449 | for (i=0; i |
||
450 | { |
||
451 | channels[i] = 0; |
||
452 | } |
||
453 | |||
454 | // This table provides step widths for pitch parameters. |
||
455 | // I fail to see that this is currently used. |
||
456 | for (i=-128 ; i<128 ; i++) |
||
457 | steptablemid[i] = (int)(pow(2.0, (i/64.0))*65536.0); |
||
458 | |||
459 | |||
460 | // Generates volume lookup tables |
||
461 | // which also turn the unsigned samples |
||
462 | // into signed samples. |
||
463 | for (i=0 ; i<128 ; i++) |
||
464 | for (j=0 ; j<256 ; j++) |
||
465 | vol_lookup[i*256+j] = (i*(j-128)*256)/127; |
||
466 | } |
||
467 | |||
468 | |||
469 | void I_SetSfxVolume(int volume) |
||
470 | { |
||
471 | // Identical to DOS. |
||
472 | // Basically, this should propagate |
||
473 | // the menu/config file setting |
||
474 | // to the state variable used in |
||
475 | // the mixing. |
||
476 | snd_SfxVolume = volume; |
||
477 | } |
||
478 | |||
479 | // MUSIC API - dummy. Some code from DOS version. |
||
480 | void I_SetMusicVolume(int volume) |
||
481 | { |
||
482 | // Internal state variable. |
||
483 | snd_MusicVolume = volume; |
||
484 | // Now set volume on output device. |
||
485 | // Whatever( snd_MusciVolume ); |
||
486 | } |
||
487 | |||
488 | |||
489 | // |
||
490 | // Retrieve the raw data lump index |
||
491 | // for a given SFX name. |
||
492 | // |
||
493 | int I_GetSfxLumpNum(sfxinfo_t* sfx) |
||
494 | { |
||
495 | char namebuf[9]; |
||
496 | sprintf(namebuf, "ds%s", sfx->name); |
||
497 | return W_GetNumForName(namebuf); |
||
498 | } |
||
499 | |||
500 | // |
||
501 | // Starting a sound means adding it |
||
502 | // to the current list of active sounds |
||
503 | // in the internal channels. |
||
504 | // As the SFX info struct contains |
||
505 | // e.g. a pointer to the raw data, |
||
506 | // it is ignored. |
||
507 | // As our sound handling does not handle |
||
508 | // priority, it is ignored. |
||
509 | // Pitching (that is, increased speed of playback) |
||
510 | // is set, but currently not used by mixing. |
||
511 | // |
||
512 | int I_StartSound( int id, int vol, int sep, int pitch, int priority, void *origin ) |
||
513 | { |
||
514 | // UNUSED |
||
515 | priority = 0; |
||
516 | |||
517 | // Debug. |
||
518 | // sprintf(MsgText, "starting sound %d", id ); |
||
519 | // WriteDebug(MsgText); |
||
520 | |||
521 | // Returns a handle (not used). |
||
522 | id = addsfx( id, vol, steptable[pitch], sep, origin ); |
||
523 | |||
524 | // sprintf(MsgText, "/handle is %d\n", id ); |
||
525 | // WriteDebug(MsgText); |
||
526 | |||
527 | return id; |
||
528 | } |
||
529 | |||
530 | // |
||
531 | // This function loops all active (internal) sound |
||
532 | // channels, retrieves a given number of samples |
||
533 | // from the raw sound data, modifies it according |
||
534 | // to the current (internal) channel parameters, |
||
535 | // mixes the per channel samples into the global |
||
536 | // mixbuffer, clamping it to the allowed range, |
||
537 | // and sets up everything for transferring the |
||
538 | // contents of the mixbuffer to the (two) |
||
539 | // hardware channels (left and right, that is). |
||
540 | // |
||
541 | // This function currently supports only 16bit. |
||
542 | // |
||
543 | void I_UpdateSound( void ) |
||
544 | { |
||
545 | #ifdef SNDINTR |
||
546 | // Debug. Count buffer misses with interrupt. |
||
547 | static int misses = 0; |
||
548 | #endif |
||
549 | |||
550 | |||
551 | // Mix current sound data. |
||
552 | // Data, from raw sound, for right and left. |
||
553 | register unsigned int sample; |
||
554 | register int dl; |
||
555 | register int dr; |
||
556 | |||
557 | // Pointers in global mixbuffer, left, right, end. |
||
558 | signed short* leftout; |
||
559 | signed short* rightout; |
||
560 | signed short* leftend; |
||
561 | // Step in mixbuffer, left and right, thus two. |
||
562 | int step; |
||
563 | |||
564 | // Mixing channel index. |
||
565 | int chan; |
||
566 | |||
567 | // Left and right channel |
||
568 | // are in global mixbuffer, alternating. |
||
569 | leftout = mixbuffer; |
||
570 | rightout = mixbuffer+1; |
||
571 | step = 2; |
||
572 | |||
573 | // Determine end, for left channel only |
||
574 | // (right channel is implicit). |
||
575 | leftend = mixbuffer + SAMPLECOUNT*step; |
||
576 | |||
577 | // Mix sounds into the mixing buffer. |
||
578 | // Loop over step*SAMPLECOUNT, |
||
579 | // that is 512 values for two channels. |
||
580 | while (leftout != leftend) |
||
581 | { |
||
582 | // Reset left/right value. |
||
583 | dl = 0; |
||
584 | dr = 0; |
||
585 | |||
586 | // Love thy L2 chache - made this a loop. |
||
587 | // Now more channels could be set at compile time |
||
588 | // as well. Thus loop those channels. |
||
589 | for ( chan = 0; chan < NUM_CHANNELS; chan++ ) |
||
590 | { |
||
591 | // Check channel, if active. |
||
592 | if (channels[ chan ]) |
||
593 | { |
||
594 | // Get the raw data from the channel. |
||
595 | sample = *channels[ chan ]; |
||
596 | // Add left and right part |
||
597 | // for this channel (sound) |
||
598 | // to the current data. |
||
599 | // Adjust volume accordingly. |
||
600 | dl += channelleftvol_lookup[ chan ][sample]; |
||
601 | dr += channelrightvol_lookup[ chan ][sample]; |
||
602 | // Increment index ??? |
||
603 | channelstepremainder[ chan ] += channelstep[ chan ]; |
||
604 | // MSB is next sample??? |
||
605 | channels[ chan ] += channelstepremainder[ chan ] >> 16; |
||
606 | // Limit to LSB??? |
||
607 | channelstepremainder[ chan ] &= 65536-1; |
||
608 | |||
609 | // Check whether we are done. |
||
610 | if (channels[ chan ] >= channelsend[ chan ]) |
||
611 | channels[ chan ] = 0; |
||
612 | } |
||
613 | } |
||
614 | |||
615 | // Clamp to range. Left hardware channel. |
||
616 | // Has been char instead of short. |
||
617 | // if (dl > 127) *leftout = 127; |
||
618 | // else if (dl < -128) *leftout = -128; |
||
619 | // else *leftout = dl; |
||
620 | |||
621 | if (dl > 0x7fff) |
||
622 | *leftout = 0x7fff; |
||
623 | else if (dl < -0x8000) |
||
624 | *leftout = -0x8000; |
||
625 | else |
||
626 | *leftout = dl; |
||
627 | |||
628 | // Same for right hardware channel. |
||
629 | if (dr > 0x7fff) |
||
630 | *rightout = 0x7fff; |
||
631 | else if (dr < -0x8000) |
||
632 | *rightout = -0x8000; |
||
633 | else |
||
634 | *rightout = dr; |
||
635 | |||
636 | // Increment current pointers in mixbuffer. |
||
637 | leftout += step; |
||
638 | rightout += step; |
||
639 | } |
||
640 | |||
641 | #ifdef SNDINTR |
||
642 | // Debug check. |
||
643 | if ( flag ) |
||
644 | { |
||
645 | misses += flag; |
||
646 | flag = 0; |
||
647 | } |
||
648 | |||
649 | if ( misses > 10 ) |
||
650 | { |
||
651 | fprintf( stderr, "I_SoundUpdate: missed 10 buffer writes\n"); |
||
652 | misses = 0; |
||
653 | } |
||
654 | |||
655 | // Increment flag for update. |
||
656 | flag++; |
||
657 | #endif |
||
658 | } |
||
659 | |||
660 | |||
661 | // |
||
662 | // This would be used to write out the mixbuffer |
||
663 | // during each game loop update. |
||
664 | // Updates sound buffer and audio device at runtime. |
||
665 | // It is called during Timer interrupt with SNDINTR. |
||
666 | // Mixing now done synchronous, and |
||
667 | // only output be done asynchronous? |
||
668 | // |
||
669 | //void |
||
670 | //I_SubmitSound(void) |
||
671 | //{ |
||
672 | // Write it to DSP device. |
||
673 | // write(audio_fd, mixbuffer, SAMPLECOUNT*BUFMUL); |
||
674 | //} |
||
675 | |||
676 | |||
677 | |||
678 | |||
679 | |||
680 | void I_ShutdownSound(void) |
||
681 | { |
||
682 | //#ifdef SNDSERV |
||
683 | // if (sndserver) |
||
684 | // { |
||
685 | // // Send a "quit" command. |
||
686 | // fprintf(sndserver, "q\n"); |
||
687 | // fflush(sndserver); |
||
688 | // } |
||
689 | //#else |
||
690 | // Wait till all pending sounds are finished. |
||
691 | int done = 0; |
||
692 | //int i; |
||
693 | |||
694 | |||
695 | // FIXME (below). |
||
696 | //fprintf( stderr, "I_ShutdownSound: NOT finishing pending sounds\n"); |
||
697 | //fflush( stderr ); |
||
698 | |||
699 | //while ( !done ) |
||
700 | //{ |
||
701 | // for( i=0 ; i<8 && !channels[i] ; i++); |
||
702 | |||
703 | // FIXME. No proper channel output. |
||
704 | //if (i==8) |
||
705 | done=1; |
||
706 | //} |
||
707 | //#ifdef SNDINTR |
||
708 | // I_SoundDelTimer(); |
||
709 | //#endif |
||
710 | |||
711 | // Cleaning up -releasing the DSP device. |
||
712 | // close( audio_fd ); |
||
713 | //#endif |
||
714 | |||
715 | // Done. |
||
716 | return; |
||
717 | } |
||
718 | |||
719 | void I_InitSound() |
||
720 | { |
||
721 | int i; |
||
722 | |||
723 | I_CreateSound(); |
||
724 | |||
725 | for (i = 1; i < NUMSFX; i++) |
||
726 | { |
||
727 | // Alias? Example is the chaingun sound linked to pistol. |
||
728 | if (!S_sfx[i].link) |
||
729 | { |
||
730 | // Load data from WAD file. |
||
731 | S_sfx[i].data = getsfx( S_sfx[i].name, &lengths[i] ); |
||
732 | } |
||
733 | else |
||
734 | { |
||
735 | // Previously loaded already? |
||
736 | S_sfx[i].data = S_sfx[i].link->data; |
||
737 | lengths[i] = lengths[(S_sfx[i].link - S_sfx)/sizeof(sfxinfo_t)]; |
||
738 | } |
||
739 | //having to crack here cuz crashing out at sound file 86 chgun |
||
740 | // incidentally the only 'linked' sound in the whole pile |
||
741 | // 10.10.98 dlw tested good. |
||
742 | if(i==86) |
||
743 | CreateSoundBuffer(i, lengths[1], S_sfx[1].data); |
||
744 | else |
||
745 | CreateSoundBuffer(i, lengths[i], S_sfx[i].data); |
||
746 | |||
747 | |||
748 | DSBControl[i].origin = NULL; |
||
749 | DSBControl[i].sfxid = i; |
||
750 | DSBControl[i].dsb_type = dsb_perm; |
||
751 | } |
||
752 | for (; i < NUM_DSBUFFERS; i++) |
||
753 | { |
||
754 | DSBControl[i].origin = NULL; |
||
755 | DSBControl[i].sfxid = -1; |
||
756 | DSBControl[i].dsb_type = dsb_temp; |
||
757 | } |
||
758 | |||
759 | } |
||
760 | |||
761 | |||
762 | |||
763 | |||
764 | // |
||
765 | // MUSIC API. |
||
766 | // Still no music done. |
||
767 | // Remains. Dummies. |
||
768 | // |
||
769 | void I_InitMusic(void) { } |
||
770 | |||
771 | static int looping=0; |
||
772 | static int musicdies=-1; |
||
773 | |||
774 | |||
775 | |||
776 | // 10.12.98 dlw - cleanup the music files |
||
777 | void I_ShutdownMusic(void) |
||
778 | { |
||
779 | int trasherror; //self explained |
||
780 | |||
781 | trasherror=unlink("doomsong.mus"); |
||
782 | trasherror=unlink("doomsong.mid"); |
||
783 | printf("I_ShutdownMusic...\n"); |
||
784 | } |
||
785 | |||
786 | |||
787 | |||
788 | |||
789 | void I_PlaySong(int handle, int looping) |
||
790 | { |
||
791 | // UNUSED. |
||
792 | handle = looping = 0; |
||
793 | musicdies = gametic + TICRATE*30; |
||
794 | } |
||
795 | |||
796 | void I_PauseSong (int handle) |
||
797 | { |
||
798 | // UNUSED. |
||
799 | handle = 0; |
||
800 | } |
||
801 | |||
802 | void I_ResumeSong (int handle) |
||
803 | { |
||
804 | // UNUSED. |
||
805 | handle = 0; |
||
806 | } |
||
807 | |||
808 | void I_StopSong(int handle) |
||
809 | { |
||
810 | // UNUSED. |
||
811 | handle = 0; |
||
812 | |||
813 | looping = 0; |
||
814 | musicdies = 0; |
||
815 | } |
||
816 | |||
817 | void I_UnRegisterSong(int handle) |
||
818 | { |
||
819 | // UNUSED. |
||
820 | handle = 0; |
||
821 | } |
||
822 | |||
823 | int I_RegisterSong(void* data) |
||
824 | { |
||
825 | // UNUSED. |
||
826 | data = NULL; |
||
827 | |||
828 | return 1; |
||
829 | } |
||
830 | |||
831 | // Is the song playing? |
||
832 | int I_QrySongPlaying(int handle) |
||
833 | { |
||
834 | // UNUSED. |
||
835 | handle = 0; |
||
836 | return looping || musicdies > gametic; |
||
837 | } |
||
838 | |||
839 | |||
840 | // |
||
841 | // Experimental stuff. |
||
842 | // A Linux timer interrupt, for asynchronous |
||
843 | // sound output. |
||
844 | // I ripped this out of the Timer class in |
||
845 | // our Difference Engine, including a few |
||
846 | // SUN remains... |
||
847 | // |
||
848 | #ifdef sun |
||
849 | typedef sigset_t tSigSet; |
||
850 | #else |
||
851 | typedef int tSigSet; |
||
852 | #endif |
||
853 | |||
854 | |||
855 | // We might use SIGVTALRM and ITIMER_VIRTUAL, if the process |
||
856 | // time independend timer happens to get lost due to heavy load. |
||
857 | // SIGALRM and ITIMER_REAL doesn't really work well. |
||
858 | // There are issues with profiling as well. |
||
859 | |||
860 | // FIXME |
||
861 | #define ITIMER_REAL 0 |
||
862 | static int /*__itimer_which*/ itimer = ITIMER_REAL; |
||
863 | |||
864 | // FIXME |
||
865 | #define SIGALRM 0 |
||
866 | static int sig = SIGALRM; |
||
867 | |||
868 | // Interrupt handler. |
||
869 | void I_HandleSoundTimer( int ignore ) |
||
870 | { |
||
871 | // Debug. |
||
872 | //fprintf( stderr, "%c", '+' ); fflush( stderr ); |
||
873 | |||
874 | // Feed sound device if necesary. |
||
875 | if ( flag ) |
||
876 | { |
||
877 | // See I_SubmitSound(). |
||
878 | // Write it to DSP device. |
||
879 | //write(audio_fd, mixbuffer, SAMPLECOUNT*BUFMUL); |
||
880 | |||
881 | // Reset flag counter. |
||
882 | flag = 0; |
||
883 | } |
||
884 | else |
||
885 | return; |
||
886 | |||
887 | // UNUSED, but required. |
||
888 | ignore = 0; |
||
889 | return; |
||
890 | } |
||
891 | |||
892 | void I_SoundDelTimer() |
||
893 | { |
||
894 | // Debug. |
||
895 | //if ( I_SoundSetTimer( 0 ) == -1) |
||
896 | // fprintf( stderr, "I_SoundDelTimer: failed to remove interrupt. Doh!\n"); |
||
897 | }>>8>>>>>256>128>128>>>>>>>>> |
||
898 |