Rev 300 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 300 | Rev 333 | ||
---|---|---|---|
Line 15... | Line 15... | ||
15 | // for more details. |
15 | // for more details. |
16 | // |
16 | // |
17 | // $Log:$ |
17 | // $Log:$ |
18 | // |
18 | // |
19 | // DESCRIPTION: |
19 | // DESCRIPTION: |
20 | // System interface for sound. |
20 | // System interface for sound. |
21 | // |
21 | // |
22 | //----------------------------------------------------------------------------- |
22 | //----------------------------------------------------------------------------- |
Line 23... | Line 23... | ||
23 | 23 | ||
24 | static const char |
24 | static const char |
Line 53... | Line 53... | ||
53 | // the size of the 16bit, 2 hardware channel (stereo) |
53 | // the size of the 16bit, 2 hardware channel (stereo) |
54 | // mixing buffer, and the samplerate of the raw data. |
54 | // mixing buffer, and the samplerate of the raw data. |
Line 55... | Line 55... | ||
55 | 55 | ||
56 | 56 | ||
57 | // Needed for calling the actual sound output. |
57 | // Needed for calling the actual sound output. |
58 | #define SAMPLECOUNT 512 |
58 | #define SAMPLECOUNT 512 |
59 | #define NUM_CHANNELS 16 |
59 | #define NUM_CHANNELS 16 |
60 | // It is 2 for 16bit, and 2 for two channels. |
60 | // It is 2 for 16bit, and 2 for two channels. |
Line 61... | Line 61... | ||
61 | #define BUFMUL 4 |
61 | #define BUFMUL 4 |
62 | #define MIXBUFFERSIZE (SAMPLECOUNT*BUFMUL) |
62 | #define MIXBUFFERSIZE (SAMPLECOUNT*BUFMUL) |
Line 63... | Line 63... | ||
63 | 63 | ||
64 | #define SAMPLERATE 11025 // Hz |
64 | #define SAMPLERATE 11025 // Hz |
Line 65... | Line 65... | ||
65 | #define SAMPLESIZE 2 // 16bit |
65 | #define SAMPLESIZE 2 // 16bit |
66 | 66 | ||
Line 67... | Line 67... | ||
67 | // The actual lengths of all sound effects. |
67 | // The actual lengths of all sound effects. |
68 | int lengths[NUMSFX]; |
68 | int lengths[NUMSFX]; |
69 | 69 | ||
70 | // The actual output device. |
70 | // The actual output device. |
71 | int audio_fd; |
71 | int audio_fd; |
Line 72... | Line 72... | ||
72 | 72 | ||
73 | // The global mixing buffer. |
73 | // The global mixing buffer. |
74 | // Basically, samples from all active internal channels |
74 | // Basically, samples from all active internal channels |
75 | // are modifed and added, and stored in the buffer |
75 | // are modifed and added, and stored in the buffer |
Line 76... | Line 76... | ||
76 | // that is submitted to the audio device. |
76 | // that is submitted to the audio device. |
77 | signed short mixbuffer[MIXBUFFERSIZE]; |
77 | signed short mixbuffer[MIXBUFFERSIZE]; |
78 | 78 | ||
Line 79... | Line 79... | ||
79 | 79 | ||
80 | // The channel step amount... |
80 | // The channel step amount... |
81 | unsigned int channelstep[NUM_CHANNELS]; |
81 | unsigned int channelstep[NUM_CHANNELS]; |
82 | // ... and a 0.16 bit remainder of last step. |
82 | // ... and a 0.16 bit remainder of last step. |
83 | unsigned int channelstepremainder[NUM_CHANNELS]; |
83 | unsigned int channelstepremainder[NUM_CHANNELS]; |
84 | 84 | ||
Line 85... | Line 85... | ||
85 | 85 | ||
86 | // The channel data pointers, start and end. |
86 | // The channel data pointers, start and end. |
87 | unsigned char* channels[NUM_CHANNELS]; |
87 | unsigned char* channels[NUM_CHANNELS]; |
88 | unsigned char* channelsend[NUM_CHANNELS]; |
88 | unsigned char* channelsend[NUM_CHANNELS]; |
89 | 89 | ||
Line 90... | Line 90... | ||
90 | 90 | ||
91 | // Time/gametic that the channel started playing, |
91 | // Time/gametic that the channel started playing, |
92 | // used to determine oldest, which automatically |
92 | // used to determine oldest, which automatically |
Line 93... | Line 93... | ||
93 | // has lowest priority. |
93 | // has lowest priority. |
94 | // In case number of active sounds exceeds |
94 | // In case number of active sounds exceeds |
Line 95... | Line 95... | ||
95 | // available channels. |
95 | // available channels. |
96 | int channelstart[NUM_CHANNELS]; |
96 | int channelstart[NUM_CHANNELS]; |
Line 97... | Line 97... | ||
97 | 97 | ||
98 | // The sound in channel handles, |
98 | // The sound in channel handles, |
99 | // determined on registration, |
99 | // determined on registration, |
Line 100... | Line 100... | ||
100 | // might be used to unregister/stop/modify, |
100 | // might be used to unregister/stop/modify, |
101 | // currently unused. |
101 | // currently unused. |
102 | int channelhandles[NUM_CHANNELS]; |
102 | int channelhandles[NUM_CHANNELS]; |
Line 153... | Line 153... | ||
153 | size = W_LumpLength( sfxlump ); |
153 | size = W_LumpLength( sfxlump ); |
Line 154... | Line 154... | ||
154 | 154 | ||
155 | // Debug. |
155 | // Debug. |
156 | // fprintf( stderr, "." ); |
156 | // fprintf( stderr, "." ); |
157 | //fprintf( stderr, " -loading %s (lump %d, %d bytes)\n", |
157 | //fprintf( stderr, " -loading %s (lump %d, %d bytes)\n", |
158 | // sfxname, sfxlump, size ); |
158 | // sfxname, sfxlump, size ); |
Line 159... | Line 159... | ||
159 | //fflush( stderr ); |
159 | //fflush( stderr ); |
Line 160... | Line 160... | ||
160 | 160 | ||
Line 191... | Line 191... | ||
191 | // which is maintained as a given number |
191 | // which is maintained as a given number |
192 | // (eight, usually) of internal channels. |
192 | // (eight, usually) of internal channels. |
193 | // Returns a handle. |
193 | // Returns a handle. |
194 | // |
194 | // |
Line 195... | Line 195... | ||
195 | 195 | ||
Line 196... | Line 196... | ||
196 | static unsigned short handlenums = 0; |
196 | static unsigned short handlenums = 0; |
197 | 197 | ||
Line 198... | Line 198... | ||
198 | int addsfx(int sfxid, int volume, int step, int seperation) |
198 | int addsfx(int sfxid, int volume, int step, int seperation) |
199 | { |
199 | { |
Line 200... | Line 200... | ||
200 | 200 | ||
201 | int i; |
201 | int i; |
202 | int rc = -1; |
202 | int rc = -1; |
Line 203... | Line 203... | ||
203 | 203 | ||
204 | int oldest = gametic; |
204 | int oldest = gametic; |
Line 205... | Line 205... | ||
205 | int oldestnum = 0; |
205 | int oldestnum = 0; |
206 | int slot; |
206 | int slot; |
207 | 207 | ||
208 | int rightvol; |
208 | int rightvol; |
209 | int leftvol; |
209 | int leftvol; |
210 | 210 | ||
211 | // Chainsaw troubles. |
211 | // Chainsaw troubles. |
212 | // Play these sound effects only one at a time. |
212 | // Play these sound effects only one at a time. |
213 | if ( sfxid == sfx_sawup |
213 | if ( sfxid == sfx_sawup |
214 | || sfxid == sfx_sawidl |
214 | || sfxid == sfx_sawidl |
215 | || sfxid == sfx_sawful |
215 | || sfxid == sfx_sawful |
216 | || sfxid == sfx_sawhit |
216 | || sfxid == sfx_sawhit |
217 | || sfxid == sfx_stnmov |
217 | || sfxid == sfx_stnmov |
218 | || sfxid == sfx_pistol ) |
218 | || sfxid == sfx_pistol ) |
219 | { |
219 | { |
220 | // Loop all channels, check. |
220 | // Loop all channels, check. |
221 | for (i=0 ; i |
221 | for (i=0 ; i |
222 | { |
222 | { |
223 | // Active, and using the same SFX? |
223 | // Active, and using the same SFX? |
224 | if ( (channels[i]) |
224 | if ( (channels[i]) |
225 | && (channelids[i] == sfxid) ) |
225 | && (channelids[i] == sfxid) ) |
226 | { |
226 | { |
227 | // Reset. |
227 | // Reset. |
228 | channels[i] = 0; |
228 | channels[i] = 0; |
Line 229... | Line 229... | ||
229 | // We are sure that iff, |
229 | // We are sure that iff, |
230 | // there will only be one. |
230 | // there will only be one. |
231 | break; |
231 | break; |
232 | } |
232 | } |
233 | } |
233 | } |
234 | } |
234 | } |
235 | 235 | ||
236 | // Loop all channels to find oldest SFX. |
236 | // Loop all channels to find oldest SFX. |
237 | for (i=0; (i |
237 | for (i=0; (i |
Line 238... | Line 238... | ||
238 | { |
238 | { |
239 | if (channelstart[i] < oldest) |
239 | if (channelstart[i] < oldest) |
240 | { |
240 | { |
241 | oldestnum = i; |
241 | oldestnum = i; |
242 | oldest = channelstart[i]; |
242 | oldest = channelstart[i]; |
243 | } |
243 | } |
244 | } |
244 | } |
245 | 245 | ||
Line 246... | Line 246... | ||
246 | // Tales from the cryptic. |
246 | // Tales from the cryptic. |
247 | // If we found a channel, fine. |
247 | // If we found a channel, fine. |
248 | // If not, we simply overwrite the first one, 0. |
248 | // If not, we simply overwrite the first one, 0. |
249 | // Probably only happens at startup. |
249 | // Probably only happens at startup. |
250 | if (i == NUM_CHANNELS) |
250 | if (i == NUM_CHANNELS) |
251 | slot = oldestnum; |
251 | slot = oldestnum; |
Line 252... | Line 252... | ||
252 | else |
252 | else |
253 | slot = i; |
253 | slot = i; |
254 | 254 | ||
Line 255... | Line 255... | ||
255 | // Okay, in the less recent channel, |
255 | // Okay, in the less recent channel, |
256 | // we will handle the new SFX. |
256 | // we will handle the new SFX. |
257 | // Set pointer to raw data. |
257 | // Set pointer to raw data. |
Line 280... | Line 280... | ||
280 | volume *=7; |
280 | volume *=7; |
281 | // Per left/right channel. |
281 | // Per left/right channel. |
282 | // x^2 seperation, |
282 | // x^2 seperation, |
283 | // adjust volume properly. |
283 | // adjust volume properly. |
284 | leftvol = |
284 | leftvol = |
285 | volume - ((volume*seperation*seperation) >> 16); ///(256*256); |
285 | volume - ((volume*seperation*seperation) >> 16); ///(256*256); |
286 | seperation = seperation - 257; |
286 | seperation = seperation - 257; |
287 | rightvol = |
287 | rightvol = |
288 | volume - ((volume*seperation*seperation) >> 16); |
288 | volume - ((volume*seperation*seperation) >> 16); |
Line 289... | Line 289... | ||
289 | 289 | ||
290 | // Sanity check, clamp volume. |
290 | // Sanity check, clamp volume. |
291 | if (rightvol < 0 || rightvol > 127) |
291 | if (rightvol < 0 || rightvol > 127) |
Line 292... | Line 292... | ||
292 | I_Error("rightvol out of bounds"); |
292 | I_Error("rightvol out of bounds"); |
293 | 293 | ||
Line 294... | Line 294... | ||
294 | if (leftvol < 0 || leftvol > 127) |
294 | if (leftvol < 0 || leftvol > 127) |
295 | I_Error("leftvol out of bounds"); |
295 | I_Error("leftvol out of bounds"); |
296 | 296 | ||
297 | // Get the proper lookup table piece |
297 | // Get the proper lookup table piece |
Line 319... | Line 319... | ||
319 | void I_SetChannels() |
319 | void I_SetChannels() |
320 | { |
320 | { |
321 | // Init internal lookups (raw data, mixing buffer, channels). |
321 | // Init internal lookups (raw data, mixing buffer, channels). |
322 | // This function sets up internal lookups used during |
322 | // This function sets up internal lookups used during |
323 | // the mixing process. |
323 | // the mixing process. |
324 | int i; |
324 | int i; |
325 | int j; |
325 | int j; |
Line 326... | Line 326... | ||
326 | 326 | ||
Line 327... | Line 327... | ||
327 | int* steptablemid = steptable + 128; |
327 | int* steptablemid = steptable + 128; |
328 | 328 | ||
329 | // Okay, reset internal mixing channels to zero. |
329 | // Okay, reset internal mixing channels to zero. |
330 | for (i=0; i |
330 | for (i=0; i |
331 | { |
331 | { |
Line 332... | Line 332... | ||
332 | channels[i] = 0; |
332 | channels[i] = 0; |
333 | } |
333 | } |
Line 334... | Line 334... | ||
334 | 334 | ||
335 | for (i=-128 ; i<128 ; i++) |
335 | // for (i=-128 ; i<128 ; i++) |
336 | steptablemid[i] = (int)(pow(2.0, (i/64.0))*65536.0); |
336 | // steptablemid[i] = (int)(pow(2.0, (i/64.0))*65536.0); |
337 | 337 | ||
338 | // Generates volume lookup tables |
338 | // Generates volume lookup tables |
339 | // which also turn the unsigned samples |
339 | // which also turn the unsigned samples |
340 | // into signed samples. |
340 | // into signed samples. |
Line 341... | Line 341... | ||
341 | for (i=0 ; i<128 ; i++) |
341 | for (i=0 ; i<128 ; i++) |
342 | for (j=0 ; j<256 ; j++) |
342 | for (j=0 ; j<256 ; j++) |
343 | vol_lookup[i*256+j] = (i*(j-128)*256)/127; |
343 | vol_lookup[i*256+j] = (i*(j-128)*256)/127; |
Line 426... | Line 426... | ||
426 | void I_UpdateSound( void ) |
426 | void I_UpdateSound( void ) |
427 | { |
427 | { |
Line 428... | Line 428... | ||
428 | 428 | ||
429 | // Mix current sound data. |
429 | // Mix current sound data. |
430 | // Data, from raw sound, for right and left. |
430 | // Data, from raw sound, for right and left. |
431 | register unsigned int sample; |
431 | register unsigned int sample; |
432 | register int dl; |
432 | register int dl; |
Line 433... | Line 433... | ||
433 | register int dr; |
433 | register int dr; |
434 | 434 | ||
435 | // Pointers in global mixbuffer, left, right, end. |
435 | // Pointers in global mixbuffer, left, right, end. |
436 | signed short* leftout; |
436 | signed short* leftout; |
437 | signed short* rightout; |
437 | signed short* rightout; |
438 | signed short* leftend; |
438 | signed short* leftend; |
Line 439... | Line 439... | ||
439 | // Step in mixbuffer, left and right, thus two. |
439 | // Step in mixbuffer, left and right, thus two. |
440 | int step; |
440 | int step; |
Line 441... | Line 441... | ||
441 | 441 | ||
442 | // Mixing channel index. |
442 | // Mixing channel index. |
443 | int chan; |
443 | int chan; |
444 | 444 | ||
Line 455... | Line 455... | ||
455 | // Mix sounds into the mixing buffer. |
455 | // Mix sounds into the mixing buffer. |
456 | // Loop over step*SAMPLECOUNT, |
456 | // Loop over step*SAMPLECOUNT, |
457 | // that is 512 values for two channels. |
457 | // that is 512 values for two channels. |
458 | while (leftout != leftend) |
458 | while (leftout != leftend) |
459 | { |
459 | { |
460 | // Reset left/right value. |
460 | // Reset left/right value. |
461 | dl = 0; |
461 | dl = 0; |
462 | dr = 0; |
462 | dr = 0; |
463 | 463 | ||
464 | // Love thy L2 chache - made this a loop. |
464 | // Love thy L2 chache - made this a loop. |
465 | // Now more channels could be set at compile time |
465 | // Now more channels could be set at compile time |
466 | // as well. Thus loop those channels. |
466 | // as well. Thus loop those channels. |
467 | for ( chan = 0; chan < NUM_CHANNELS; chan++ ) |
467 | for ( chan = 0; chan < NUM_CHANNELS; chan++ ) |
468 | { |
468 | { |
469 | // Check channel, if active. |
469 | // Check channel, if active. |
470 | if (channels[ chan ]) |
470 | if (channels[ chan ]) |
471 | { |
471 | { |
472 | // Get the raw data from the channel. |
472 | // Get the raw data from the channel. |
473 | sample = *channels[ chan ]; |
473 | sample = *channels[ chan ]; |
474 | // Add left and right part |
474 | // Add left and right part |
475 | // for this channel (sound) |
475 | // for this channel (sound) |
476 | // to the current data. |
476 | // to the current data. |
477 | // Adjust volume accordingly. |
477 | // Adjust volume accordingly. |
478 | dl += channelleftvol_lookup[ chan ][sample]; |
478 | dl += channelleftvol_lookup[ chan ][sample]; |
479 | dr += channelrightvol_lookup[ chan ][sample]; |
479 | dr += channelrightvol_lookup[ chan ][sample]; |
480 | 480 | ||
481 | channelstepremainder[ chan ] += channelstep[ chan ]; |
481 | channelstepremainder[ chan ] += channelstep[ chan ]; |
482 | 482 | ||
483 | channels[ chan ] += channelstepremainder[ chan ] >> 16; |
483 | channels[ chan ] += channelstepremainder[ chan ] >> 16; |
484 | 484 | ||
485 | channelstepremainder[ chan ] &= 65536-1; |
485 | channelstepremainder[ chan ] &= 65536-1; |
486 | 486 | ||
487 | // Check whether we are done. |
487 | // Check whether we are done. |
488 | if (channels[ chan ] >= channelsend[ chan ]) |
488 | if (channels[ chan ] >= channelsend[ chan ]) |
489 | channels[ chan ] = 0; |
489 | channels[ chan ] = 0; |
490 | } |
490 | } |
491 | } |
491 | } |
492 | 492 | ||
493 | // Clamp to range. Left hardware channel. |
493 | // Clamp to range. Left hardware channel. |
494 | // Has been char instead of short. |
494 | // Has been char instead of short. |
495 | // if (dl > 127) *leftout = 127; |
495 | // if (dl > 127) *leftout = 127; |
496 | // else if (dl < -128) *leftout = -128; |
496 | // else if (dl < -128) *leftout = -128; |
497 | // else *leftout = dl; |
497 | // else *leftout = dl; |
498 | 498 | ||
499 | if (dl > 0x7fff) |
499 | if (dl > 0x7fff) |
500 | *leftout = 0x7fff; |
500 | *leftout = 0x7fff; |
501 | else if (dl < -0x8000) |
501 | else if (dl < -0x8000) |
502 | *leftout = -0x8000; |
502 | *leftout = -0x8000; |
503 | else |
503 | else |
504 | *leftout = dl; |
504 | *leftout = dl; |
505 | 505 | ||
506 | // Same for right hardware channel. |
506 | // Same for right hardware channel. |
507 | if (dr > 0x7fff) |
507 | if (dr > 0x7fff) |
508 | *rightout = 0x7fff; |
508 | *rightout = 0x7fff; |
509 | else if (dr < -0x8000) |
509 | else if (dr < -0x8000) |
510 | *rightout = -0x8000; |
510 | *rightout = -0x8000; |
511 | else |
511 | else |
512 | *rightout = dr; |
512 | *rightout = dr; |
513 | 513 | ||
514 | // Increment current pointers in mixbuffer. |
514 | // Increment current pointers in mixbuffer. |
515 | leftout += step; |
515 | leftout += step; |
516 | rightout += step; |
516 | rightout += step; |
517 | } |
517 | } |
518 | I_SubmitSound(mixbuffer); |
518 | // I_SubmitSound(mixbuffer); |
519 | } |
519 | } |
Line 520... | Line 520... | ||
520 | 520 | ||
521 | 521 | ||
Line 575... | Line 575... | ||
575 | // Alias? Example is the chaingun sound linked to pistol. |
575 | // Alias? Example is the chaingun sound linked to pistol. |
576 | if (!S_sfx[i].link) |
576 | if (!S_sfx[i].link) |
577 | { |
577 | { |
578 | // Load data from WAD file. |
578 | // Load data from WAD file. |
579 | S_sfx[i].data = getsfx( S_sfx[i].name, &lengths[i] ); |
579 | S_sfx[i].data = getsfx( S_sfx[i].name, &lengths[i] ); |
580 | } |
580 | } |
581 | else |
581 | else |
582 | { |
582 | { |
583 | // Previously loaded already? |
583 | // Previously loaded already? |
584 | S_sfx[i].data = S_sfx[i].link->data; |
584 | S_sfx[i].data = S_sfx[i].link->data; |
585 | lengths[i] = lengths[(S_sfx[i].link - S_sfx)/sizeof(sfxinfo_t)]; |
585 | lengths[i] = lengths[(S_sfx[i].link - S_sfx)/sizeof(sfxinfo_t)]; |
Line 601... | Line 601... | ||
601 | // |
601 | // |
602 | // MUSIC API. |
602 | // MUSIC API. |
603 | // Still no music done. |
603 | // Still no music done. |
604 | // Remains. Dummies. |
604 | // Remains. Dummies. |
605 | // |
605 | // |
606 | void I_InitMusic(void) { } |
606 | void I_InitMusic(void) { } |
607 | void I_ShutdownMusic(void) { } |
607 | void I_ShutdownMusic(void) { } |
Line 608... | Line 608... | ||
608 | 608 | ||
609 | static int looping=0; |
609 | static int looping=0; |
Line 610... | Line 610... | ||
610 | static int musicdies=-1; |
610 | static int musicdies=-1; |
611 | 611 | ||
612 | void I_PlaySong(int handle, int looping) |
612 | void I_PlaySong(int handle, int looping) |
613 | { |
613 | { |