diff options
Diffstat (limited to 'apps/plugins/doom/i_sound.c')
-rw-r--r-- | apps/plugins/doom/i_sound.c | 607 |
1 files changed, 607 insertions, 0 deletions
diff --git a/apps/plugins/doom/i_sound.c b/apps/plugins/doom/i_sound.c new file mode 100644 index 0000000000..471b0ee193 --- /dev/null +++ b/apps/plugins/doom/i_sound.c | |||
@@ -0,0 +1,607 @@ | |||
1 | /* Emacs style mode select -*- C++ -*- | ||
2 | *----------------------------------------------------------------------------- | ||
3 | * | ||
4 | * | ||
5 | * PrBoom a Doom port merged with LxDoom and LSDLDoom | ||
6 | * based on BOOM, a modified and improved DOOM engine | ||
7 | * Copyright (C) 1999 by | ||
8 | * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman | ||
9 | * Copyright (C) 1999-2000 by | ||
10 | * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | ||
25 | * 02111-1307, USA. | ||
26 | * | ||
27 | * DESCRIPTION: | ||
28 | * System interface for sound. | ||
29 | * | ||
30 | *----------------------------------------------------------------------------- | ||
31 | */ | ||
32 | |||
33 | #include "z_zone.h" | ||
34 | |||
35 | #include "i_system.h" | ||
36 | #include "i_sound.h" | ||
37 | #include "m_argv.h" | ||
38 | #include "m_misc.h" | ||
39 | #include "w_wad.h" | ||
40 | #include "m_swap.h" | ||
41 | #include "d_main.h" | ||
42 | #include "doomdef.h" | ||
43 | #include "rockmacros.h" | ||
44 | |||
45 | // The number of internal mixing channels, | ||
46 | // the samples calculated for each mixing step, | ||
47 | // the size of the 16bit, 2 hardware channel (stereo) | ||
48 | // mixing buffer, and the samplerate of the raw data. | ||
49 | |||
50 | // Needed for calling the actual sound output. | ||
51 | #define SAMPLECOUNT 512 | ||
52 | |||
53 | #define NUM_CHANNELS 16 | ||
54 | // It is 2 for 16bit, and 2 for two channels. | ||
55 | #define BUFMUL 4 | ||
56 | #define MIXBUFFERSIZE (SAMPLECOUNT*BUFMUL) | ||
57 | |||
58 | #define SAMPLERATE 11025 // 44100 22050 11025 | ||
59 | #define SAMPLESIZE 2 // 16bit | ||
60 | |||
61 | // The global mixing buffer. | ||
62 | // Basically, samples from all active internal channels | ||
63 | // are modifed and added, and stored in the buffer | ||
64 | // that is submitted to the audio device. | ||
65 | signed short mixbuffer[MIXBUFFERSIZE]; | ||
66 | |||
67 | typedef struct { | ||
68 | // SFX id of the playing sound effect. | ||
69 | // Used to catch duplicates (like chainsaw). | ||
70 | int id; | ||
71 | // The channel step amount... | ||
72 | unsigned int step; | ||
73 | // ... and a 0.16 bit remainder of last step. | ||
74 | unsigned int stepremainder; | ||
75 | unsigned int samplerate; | ||
76 | // The channel data pointers, start and end. | ||
77 | const unsigned char* data; | ||
78 | const unsigned char* enddata; | ||
79 | // Time/gametic that the channel started playing, | ||
80 | // used to determine oldest, which automatically | ||
81 | // has lowest priority. | ||
82 | // In case number of active sounds exceeds | ||
83 | // available channels. | ||
84 | int starttime; | ||
85 | // Hardware left and right channel volume lookup. | ||
86 | int *leftvol_lookup; | ||
87 | int *rightvol_lookup; | ||
88 | } channel_info_t; | ||
89 | |||
90 | channel_info_t channelinfo[NUM_CHANNELS]; | ||
91 | |||
92 | int *vol_lookup; // Volume lookups. | ||
93 | |||
94 | int steptable[256]; // Pitch to stepping lookup. (Not setup properly right now) | ||
95 | |||
96 | // | ||
97 | // This function loads the sound data from the WAD lump for single sound. | ||
98 | // It is used to cache all the sounddata at startup. | ||
99 | // | ||
100 | void* getsfx( const char* sfxname ) | ||
101 | { | ||
102 | unsigned char* sfx; | ||
103 | unsigned char* paddedsfx; | ||
104 | int size; | ||
105 | char name[20]; | ||
106 | int sfxlump; | ||
107 | |||
108 | // Get the sound data from the WAD, allocate lump | ||
109 | // in zone memory. | ||
110 | snprintf(name, sizeof(name), "ds%s", sfxname); | ||
111 | |||
112 | // Now, there is a severe problem with the sound handling, in it is not | ||
113 | // (yet/anymore) gamemode aware. That means, sounds from DOOM II will be | ||
114 | // requested even with DOOM shareware. | ||
115 | // The sound list is wired into sounds.c, which sets the external variable. | ||
116 | // I do not do runtime patches to that variable. Instead, we will use a | ||
117 | // default sound for replacement. | ||
118 | if ( W_CheckNumForName(name) == -1 ) | ||
119 | sfxlump = W_GetNumForName("dspistol"); | ||
120 | else | ||
121 | sfxlump = W_GetNumForName(name); | ||
122 | |||
123 | size = W_LumpLength( sfxlump ); | ||
124 | |||
125 | sfx = (unsigned char*)W_CacheLumpNum( sfxlump); | ||
126 | |||
127 | paddedsfx = (unsigned char*)malloc( size ); // Allocate from memory. | ||
128 | memcpy(paddedsfx, sfx, size ); // Now copy and pad. | ||
129 | W_UnlockLumpNum(sfxlump); // Remove the cached lump. | ||
130 | |||
131 | return (void *) (paddedsfx); // Return allocated data. | ||
132 | } | ||
133 | |||
134 | /* cph | ||
135 | * stopchan | ||
136 | * Stops a sound | ||
137 | */ | ||
138 | static void stopchan(int i) | ||
139 | { | ||
140 | channelinfo[i].data=NULL; | ||
141 | } | ||
142 | |||
143 | // | ||
144 | // This function adds a sound to the | ||
145 | // list of currently active sounds, | ||
146 | // which is maintained as a given number | ||
147 | // (eight, usually) of internal channels. | ||
148 | // Returns a handle. | ||
149 | // | ||
150 | int addsfx( int sfxid, int channel) | ||
151 | { | ||
152 | stopchan(channel); | ||
153 | |||
154 | // We will handle the new SFX. | ||
155 | // Set pointer to raw data. | ||
156 | { | ||
157 | int lump = S_sfx[sfxid].lumpnum; | ||
158 | size_t len = W_LumpLength(lump); | ||
159 | |||
160 | /* Find padded length */ | ||
161 | len -= 8; | ||
162 | channelinfo[channel].data = S_sfx[sfxid].data; | ||
163 | |||
164 | /* Set pointer to end of raw data. */ | ||
165 | channelinfo[channel].enddata = channelinfo[channel].data + len - 1; | ||
166 | channelinfo[channel].samplerate = (channelinfo[channel].data[3]<<8)+channelinfo[channel].data[2]; | ||
167 | channelinfo[channel].data += 8; /* Skip header */ | ||
168 | } | ||
169 | |||
170 | channelinfo[channel].stepremainder = 0; | ||
171 | // Should be gametic, I presume. | ||
172 | channelinfo[channel].starttime = gametic; | ||
173 | |||
174 | // Preserve sound SFX id, | ||
175 | // e.g. for avoiding duplicates of chainsaw. | ||
176 | channelinfo[channel].id = sfxid; | ||
177 | |||
178 | return channel; | ||
179 | } | ||
180 | |||
181 | static void updateSoundParams(int handle, int volume, int seperation, int pitch) | ||
182 | { | ||
183 | int rightvol; | ||
184 | int leftvol; | ||
185 | int slot = handle; | ||
186 | int step = steptable[pitch]; | ||
187 | #ifdef RANGECHECK | ||
188 | if (handle>=NUM_CHANNELS) | ||
189 | I_Error("I_UpdateSoundParams: handle out of range"); | ||
190 | #endif | ||
191 | // Set stepping | ||
192 | // MWM 2000-12-24: Calculates proportion of channel samplerate | ||
193 | // to global samplerate for mixing purposes. | ||
194 | // Patched to shift left *then* divide, to minimize roundoff errors | ||
195 | // as well as to use SAMPLERATE as defined above, not to assume 11025 Hz | ||
196 | if (pitched_sounds) | ||
197 | channelinfo[slot].step = step + (((channelinfo[slot].samplerate<<16)/SAMPLERATE)-65536); | ||
198 | else | ||
199 | channelinfo[slot].step = ((channelinfo[slot].samplerate<<16)/SAMPLERATE); | ||
200 | |||
201 | // Separation, that is, orientation/stereo. | ||
202 | // range is: 1 - 256 | ||
203 | seperation += 1; | ||
204 | |||
205 | // Per left/right channel. | ||
206 | // x^2 seperation, | ||
207 | // adjust volume properly. | ||
208 | leftvol = volume - ((volume*seperation*seperation) >> 16); | ||
209 | seperation = seperation - 257; | ||
210 | rightvol= volume - ((volume*seperation*seperation) >> 16); | ||
211 | |||
212 | // Sanity check, clamp volume. | ||
213 | if (rightvol < 0 || rightvol > 127) | ||
214 | I_Error("rightvol out of bounds"); | ||
215 | |||
216 | if (leftvol < 0 || leftvol > 127) | ||
217 | I_Error("leftvol out of bounds"); | ||
218 | |||
219 | // Get the proper lookup table piece | ||
220 | // for this volume level??? | ||
221 | channelinfo[slot].leftvol_lookup = &vol_lookup[leftvol*256]; | ||
222 | channelinfo[slot].rightvol_lookup = &vol_lookup[rightvol*256]; | ||
223 | } | ||
224 | |||
225 | void I_UpdateSoundParams(int handle, int volume, int seperation, int pitch) | ||
226 | { | ||
227 | updateSoundParams(handle, volume, seperation, pitch); | ||
228 | } | ||
229 | |||
230 | // | ||
231 | // SFX API | ||
232 | // Note: this was called by S_Init. | ||
233 | // However, whatever they did in the | ||
234 | // old DPMS based DOS version, this | ||
235 | // were simply dummies in the Linux | ||
236 | // version. | ||
237 | // See soundserver initdata(). | ||
238 | // | ||
239 | void I_SetChannels() | ||
240 | { | ||
241 | // Init internal lookups (raw data, mixing buffer, channels). | ||
242 | // This function sets up internal lookups used during | ||
243 | // the mixing process. | ||
244 | int i; | ||
245 | int j; | ||
246 | int* steptablemid = steptable + 128; | ||
247 | |||
248 | // Okay, reset internal mixing channels to zero. | ||
249 | for (i=0; i<NUM_CHANNELS; i++) | ||
250 | memset(&channelinfo[i],0,sizeof(channel_info_t)); | ||
251 | |||
252 | // This table provides step widths for pitch parameters. | ||
253 | for (i=-128 ; i<128 ; i++) | ||
254 | steptablemid[i]=2; | ||
255 | // steptablemid[i] = (int)(pow(1.2, ((double)i/(64.0*SAMPLERATE/11025)))*65536.0); | ||
256 | |||
257 | // Generates volume lookup tables | ||
258 | // which also turn the unsigned samples | ||
259 | // into signed samples. | ||
260 | for (i=0 ; i<128 ; i++) | ||
261 | for (j=0 ; j<256 ; j++) | ||
262 | vol_lookup[i*256+j] = 3*(i*(j-128)*256)/191; | ||
263 | } | ||
264 | |||
265 | void I_SetSfxVolume(int volume) | ||
266 | { | ||
267 | // Identical to DOS. | ||
268 | // Basically, this should propagate | ||
269 | // the menu/config file setting | ||
270 | // to the state variable used in | ||
271 | // the mixing. | ||
272 | snd_SfxVolume = volume; | ||
273 | } | ||
274 | |||
275 | // MUSIC API - dummy. Some code from DOS version. | ||
276 | void I_SetMusicVolume(int volume) | ||
277 | { | ||
278 | // Internal state variable. | ||
279 | snd_MusicVolume = volume; | ||
280 | // Now set volume on output device. | ||
281 | // Whatever( snd_MusciVolume ); | ||
282 | } | ||
283 | |||
284 | // | ||
285 | // Retrieve the raw data lump index | ||
286 | // for a given SFX name. | ||
287 | // | ||
288 | int I_GetSfxLumpNum(sfxinfo_t* sfx) | ||
289 | { | ||
290 | char namebuf[9]; | ||
291 | snprintf(namebuf, sizeof(namebuf), "ds%s", sfx->name); | ||
292 | return W_GetNumForName(namebuf); | ||
293 | } | ||
294 | |||
295 | // | ||
296 | // Starting a sound means adding it | ||
297 | // to the current list of active sounds | ||
298 | // in the internal channels. | ||
299 | // As the SFX info struct contains | ||
300 | // e.g. a pointer to the raw data, | ||
301 | // it is ignored. | ||
302 | // As our sound handling does not handle | ||
303 | // priority, it is ignored. | ||
304 | // Pitching (that is, increased speed of playback) | ||
305 | // is set, but currently not used by mixing. | ||
306 | // | ||
307 | int I_StartSound(int id, int channel, int vol, int sep, int pitch, int priority) | ||
308 | { | ||
309 | (void)priority; | ||
310 | int handle; | ||
311 | |||
312 | // Returns a handle (not used). | ||
313 | handle = addsfx(id,channel); | ||
314 | |||
315 | #ifdef RANGECHECK | ||
316 | if (handle>=NUM_CHANNELS) | ||
317 | I_Error("I_StartSound: handle out of range"); | ||
318 | #endif | ||
319 | updateSoundParams(handle, vol, sep, pitch); | ||
320 | |||
321 | return handle; | ||
322 | } | ||
323 | |||
324 | void I_StopSound (int handle) | ||
325 | { | ||
326 | #ifdef RANGECHECK | ||
327 | if (handle>=NUM_CHANNELS) | ||
328 | I_Error("I_StopSound: handle out of range"); | ||
329 | #endif | ||
330 | stopchan(handle); | ||
331 | } | ||
332 | |||
333 | int I_SoundIsPlaying(int handle) | ||
334 | { | ||
335 | #ifdef RANGECHECK | ||
336 | if (handle>=NUM_CHANNELS) | ||
337 | I_Error("I_SoundIsPlaying: handle out of range"); | ||
338 | #endif | ||
339 | return channelinfo[handle].data != NULL; | ||
340 | } | ||
341 | |||
342 | // | ||
343 | // This function loops all active (internal) sound | ||
344 | // channels, retrieves a given number of samples | ||
345 | // from the raw sound data, modifies it according | ||
346 | // to the current (internal) channel parameters, | ||
347 | // mixes the per channel samples into the given | ||
348 | // mixing buffer, and clamping it to the allowed | ||
349 | // range. | ||
350 | // | ||
351 | // This function currently supports only 16bit. | ||
352 | // | ||
353 | |||
354 | bool swap=0; | ||
355 | bool lastswap=1; | ||
356 | // Pointers in global mixbuffer, left, right, end. | ||
357 | signed short* leftout; | ||
358 | signed short* rightout; | ||
359 | signed short* leftend; | ||
360 | |||
361 | void I_UpdateSound( void ) | ||
362 | { | ||
363 | // Mix current sound data. | ||
364 | // Data, from raw sound, for right and left. | ||
365 | register unsigned char sample; | ||
366 | register int dl; | ||
367 | register int dr; | ||
368 | |||
369 | // Step in mixbuffer, left and right, thus two. | ||
370 | int step; | ||
371 | |||
372 | // Mixing channel index. | ||
373 | int chan; | ||
374 | |||
375 | if(lastswap==swap) | ||
376 | return; | ||
377 | lastswap=swap; | ||
378 | |||
379 | // Left and right channel | ||
380 | // are in global mixbuffer, alternating. | ||
381 | leftout = (swap ? mixbuffer : mixbuffer + SAMPLECOUNT*2); | ||
382 | rightout = (swap ? mixbuffer : mixbuffer + SAMPLECOUNT*2)+1; | ||
383 | step = 2; | ||
384 | |||
385 | // Determine end, for left channel only | ||
386 | // (right channel is implicit). | ||
387 | leftend = (swap ? mixbuffer : mixbuffer + SAMPLECOUNT*2) + SAMPLECOUNT*step; | ||
388 | |||
389 | // Mix sounds into the mixing buffer. | ||
390 | // Loop over step*SAMPLECOUNT, | ||
391 | // that is 512 values for two channels. | ||
392 | while (leftout != leftend) | ||
393 | { | ||
394 | // Reset left/right value. | ||
395 | dl = 0; | ||
396 | dr = 0; | ||
397 | |||
398 | // Love thy L2 chache - made this a loop. | ||
399 | // Now more channels could be set at compile time | ||
400 | // as well. Thus loop those channels. | ||
401 | for ( chan = 0; chan < NUM_CHANNELS; chan++ ) | ||
402 | { | ||
403 | // Check channel, if active. | ||
404 | if (channelinfo[chan].data) | ||
405 | { | ||
406 | // Get the raw data from the channel. | ||
407 | sample = (((unsigned int)channelinfo[chan].data[0] * (0x10000 - channelinfo[chan].stepremainder)) | ||
408 | + ((unsigned int)channelinfo[chan].data[1] * (channelinfo[chan].stepremainder))) >> 16; | ||
409 | // Add left and right part | ||
410 | // for this channel (sound) | ||
411 | // to the current data. | ||
412 | // Adjust volume accordingly. | ||
413 | dl += channelinfo[chan].leftvol_lookup[sample]; | ||
414 | dr += channelinfo[chan].rightvol_lookup[sample]; | ||
415 | // Increment index ??? | ||
416 | channelinfo[chan].stepremainder += channelinfo[chan].step; | ||
417 | // MSB is next sample??? | ||
418 | channelinfo[chan].data += channelinfo[chan].stepremainder >> 16; | ||
419 | // Limit to LSB??? | ||
420 | channelinfo[chan].stepremainder &= 0xffff; | ||
421 | |||
422 | // Check whether we are done. | ||
423 | if (channelinfo[chan].data >= channelinfo[chan].enddata) | ||
424 | stopchan(chan); | ||
425 | } | ||
426 | } | ||
427 | |||
428 | // Clamp to range. Left hardware channel. | ||
429 | // Has been char instead of short. | ||
430 | // if (dl > 127) *leftout = 127; | ||
431 | // else if (dl < -128) *leftout = -128; | ||
432 | // else *leftout = dl; | ||
433 | |||
434 | if (dl > 0x7fff) | ||
435 | *leftout = 0x7fff; | ||
436 | else if (dl < -0x8000) | ||
437 | *leftout = -0x8000; | ||
438 | else | ||
439 | *leftout = (signed short)dl; | ||
440 | |||
441 | // Same for right hardware channel. | ||
442 | if (dr > 0x7fff) | ||
443 | *rightout = 0x7fff; | ||
444 | else if (dr < -0x8000) | ||
445 | *rightout = -0x8000; | ||
446 | else | ||
447 | *rightout = (signed short)dr; | ||
448 | |||
449 | // Increment current pointers in mixbuffer. | ||
450 | leftout += step; | ||
451 | rightout += step; | ||
452 | } | ||
453 | } | ||
454 | |||
455 | // | ||
456 | // This would be used to write out the mixbuffer | ||
457 | // during each game loop update. | ||
458 | // Updates sound buffer and audio device at runtime. | ||
459 | // It is called during Timer interrupt with SNDINTR. | ||
460 | // Mixing now done synchronous, and | ||
461 | // only output be done asynchronous? | ||
462 | // | ||
463 | |||
464 | void get_more(unsigned char** start, size_t* size) | ||
465 | { | ||
466 | // This code works fine, the only problem is that doom runs slower then the sound | ||
467 | // updates (sometimes). This code forces the update if the sound hasn't been | ||
468 | // remixed. | ||
469 | if(lastswap!=swap) | ||
470 | I_UpdateSound(); // Force sound update (We don't want stutters) | ||
471 | |||
472 | *start = (unsigned char*)((swap ? mixbuffer : mixbuffer + SAMPLECOUNT*2)); | ||
473 | *size = SAMPLECOUNT*2*sizeof(short); | ||
474 | swap=!swap; | ||
475 | } | ||
476 | |||
477 | |||
478 | void I_SubmitSound(void) | ||
479 | { | ||
480 | if (nosfxparm) | ||
481 | return; | ||
482 | |||
483 | #if !defined(SIMULATOR) | ||
484 | rb->pcm_play_data(&get_more, NULL, 0); | ||
485 | #endif | ||
486 | } | ||
487 | |||
488 | void I_ShutdownSound(void) | ||
489 | { | ||
490 | #if !defined(SIMULATOR) | ||
491 | rb->pcm_play_stop(); | ||
492 | rb->pcm_set_frequency(44100); // 44100 | ||
493 | #endif | ||
494 | } | ||
495 | |||
496 | void I_InitSound() | ||
497 | { | ||
498 | int i; | ||
499 | |||
500 | // Initialize external data (all sounds) at start, keep static. | ||
501 | printf( "I_InitSound: "); | ||
502 | #if !defined(SIMULATOR) | ||
503 | rb->pcm_play_stop(); | ||
504 | rb->pcm_set_frequency(SAMPLERATE); | ||
505 | #endif | ||
506 | |||
507 | vol_lookup=malloc(128*256*sizeof(int)); | ||
508 | |||
509 | for (i=1 ; i<NUMSFX ; i++) | ||
510 | { | ||
511 | if (!S_sfx[i].link) // Alias? Example is the chaingun sound linked to pistol. | ||
512 | S_sfx[i].data = getsfx( S_sfx[i].name); // Load data from WAD file. | ||
513 | else | ||
514 | S_sfx[i].data = S_sfx[i].link->data; // Previously loaded already? | ||
515 | } | ||
516 | |||
517 | printf( " pre-cached all sound data\n"); | ||
518 | |||
519 | // Now initialize mixbuffer with zero. | ||
520 | for ( i = 0; i< MIXBUFFERSIZE; i++ ) | ||
521 | mixbuffer[i] = 0; | ||
522 | |||
523 | // Finished initialization. | ||
524 | printf("I_InitSound: sound module ready\n"); | ||
525 | } | ||
526 | |||
527 | // | ||
528 | // MUSIC API. | ||
529 | // Still no music done. | ||
530 | // Remains. Dummies. | ||
531 | // | ||
532 | void I_InitMusic(void) { | ||
533 | } | ||
534 | void I_ShutdownMusic(void) { | ||
535 | } | ||
536 | |||
537 | static int looping=0; | ||
538 | static int musicdies=-1; | ||
539 | |||
540 | void I_PlaySong(int handle, int looping) | ||
541 | { | ||
542 | // UNUSED. | ||
543 | handle = looping = 0; | ||
544 | musicdies = gametic + TICRATE*30; | ||
545 | } | ||
546 | |||
547 | void I_PauseSong (int handle) | ||
548 | { | ||
549 | // UNUSED. | ||
550 | handle = 0; | ||
551 | } | ||
552 | |||
553 | void I_ResumeSong (int handle) | ||
554 | { | ||
555 | // UNUSED. | ||
556 | handle = 0; | ||
557 | } | ||
558 | |||
559 | void I_StopSong(int handle) | ||
560 | { | ||
561 | // UNUSED. | ||
562 | handle = 0; | ||
563 | |||
564 | looping = 0; | ||
565 | musicdies = 0; | ||
566 | } | ||
567 | |||
568 | void I_UnRegisterSong(int handle) | ||
569 | { | ||
570 | // UNUSED. | ||
571 | handle = 0; | ||
572 | } | ||
573 | |||
574 | int I_RegisterSong(const void *data) | ||
575 | { | ||
576 | // UNUSED. | ||
577 | data = NULL; | ||
578 | |||
579 | return 1; | ||
580 | } | ||
581 | |||
582 | // Is the song playing? | ||
583 | int I_QrySongPlaying(int handle) | ||
584 | { | ||
585 | // UNUSED. | ||
586 | handle = 0; | ||
587 | return looping || musicdies > gametic; | ||
588 | } | ||
589 | |||
590 | // Interrupt handler. | ||
591 | void I_HandleSoundTimer( int ignore ) | ||
592 | { | ||
593 | (void)ignore; | ||
594 | } | ||
595 | |||
596 | // Get the interrupt. Set duration in millisecs. | ||
597 | int I_SoundSetTimer( int duration_of_tick ) | ||
598 | { | ||
599 | (void)duration_of_tick; | ||
600 | // Error is -1. | ||
601 | return 0; | ||
602 | } | ||
603 | |||
604 | // Remove the interrupt. Set duration to zero. | ||
605 | void I_SoundDelTimer(void) | ||
606 | { | ||
607 | } | ||