5 #include "w_wad.h" // W_GetNumForName()
8 /* The number of internal mixing channels,
9 ** the samples calculated for each mixing step,
10 ** the size of the 16bit, 2 hardware channel (stereo)
11 ** mixing buffer, and the samplerate of the raw data.
14 /* Needed for calling the actual sound output. */
15 #define SAMPLECOUNT (512<<2)
16 #define NUM_CHANNELS 8
17 /* It is 2 for 16bit, and 2 for two channels */
19 #define MIXBUFFERSIZE (SAMPLECOUNT*BUFMUL)
21 /* The actual lengths of all sound effects. */
24 /* The actual output device. */
27 /* The global mixing buffer.
28 ** Basically, samples from all active internal channels
29 ** are modified and added, and stored in the buffer
30 ** that is submitted to the audio device.
32 signed short mixbuffer[MIXBUFFERSIZE];
34 /* The channel step amount... */
35 uint channelstep[NUM_CHANNELS];
36 /* ... and a 0.16 bit remainder of last step. */
37 uint channelstepremainder[NUM_CHANNELS];
39 /* The channel data pointers, start and end. */
40 uchar* channels[NUM_CHANNELS];
41 uchar* channelsend[NUM_CHANNELS];
43 /* Time/gametic that the channel started playing,
44 ** used to determine oldest, which automatically
45 ** has lowest priority.
46 ** In case number of active sounds exceeds
47 ** available channels.
49 int channelstart[NUM_CHANNELS];
51 /* The sound in channel handles,
52 ** determined on registration,
53 ** might be used to unregister/stop/modify,
56 int channelhandles[NUM_CHANNELS];
58 /* SFX id of the playing sound effect.
59 ** Used to catch duplicates (like chainsaw).
61 int channelids[NUM_CHANNELS];
63 /* Pitch to stepping lookup, unused. */
67 int vol_lookup[128*256];
69 /* Hardware left and right channel volume lookup. */
70 int* channelleftvol_lookup[NUM_CHANNELS];
71 int* channelrightvol_lookup[NUM_CHANNELS];
73 static void* getsfx(char *sfxname, int *len)
83 /* Get the sound data from the WAD, allocate lump
85 sprintf(name, "ds%s", sfxname);
87 /* Now, there is a severe problem with the
88 ** sound handling, in it is not (yet/anymore)
89 ** gamemode aware. That means, sounds from
90 ** DOOM II will be requested even with DOOM
92 ** The sound list is wired into sounds.c,
93 ** which sets the external variable.
94 ** I do not do runtime patches to that
95 ** variable. Instead, we will use a
96 ** default sound for replacement.
98 if ( W_CheckNumForName(name) == -1 )
99 sfxlump = W_GetNumForName("dspistol");
101 sfxlump = W_GetNumForName(name);
103 size = W_LumpLength( sfxlump );
105 sfx = (uchar *)W_CacheLumpNum(sfxlump, PU_STATIC);
107 /* Pads the sound effect out to the mixing buffer size.
108 ** The original realloc would interfere with zone memory.
110 paddedsize = ((size-8 + (SAMPLECOUNT-1)) / SAMPLECOUNT) * SAMPLECOUNT;
112 /* Allocate from zone memory. */
113 paddedsfx = (uchar *)Z_Malloc(paddedsize+8, PU_STATIC, 0);
115 /* Now copy and pad. */
116 memcpy(paddedsfx, sfx, size);
117 for (i=size ; i<paddedsize+8 ; i++)
120 /* Remove the cached lump. */
123 /* Preserve padded length. */
126 /* Return allocated padded data. */
127 return (void *)(paddedsfx + 8);
130 void I_InitSound(void)
134 audio_fd = open("/dev/audio", ORDWR);
136 printf("WARN Failed to open /dev/audio, sound disabled\n");
138 /* Initialize external data (all sounds) at start, keep static. */
139 for (i=1 ; i<NUMSFX ; i++)
141 /* Alias? Example is the chaingun sound linked to pistol. */
144 /* Load data from WAD file. */
145 S_sfx[i].data = getsfx( S_sfx[i].name, &lengths[i] );
149 /* Previously loaded already? */
150 S_sfx[i].data = S_sfx[i].link->data;
151 lengths[i] = lengths[(S_sfx[i].link - S_sfx)/sizeof(sfxinfo_t)];
155 /* Now initialize mixbuffer with zero. */
156 memset(mixbuffer, 0, sizeof(mixbuffer));
159 /* This function loops all active (internal) sound
160 ** channels, retrieves a given number of samples
161 ** from the raw sound data, modifies it according
162 ** to the current (internal) channel parameters,
163 ** mixes the per-channel samples into the global
164 ** mixbuffer, clamping it to the allowed range,
165 ** and sets up everything for transferring the
166 ** contents of the mixbuffer to the (two)
167 ** hardware channels (left and right, that is).
169 ** This function currently supports only 16bit.
171 void I_UpdateSound(void)
173 /* Mix current sound data.
174 ** Data, from raw sound, for right and left.
176 register uint sample;
180 /* Pointers in global mixbuffer, left, right, end. */
181 signed short *leftout;
182 signed short *rightout;
183 signed short *leftend;
184 /* Step in mixbuffer, left and right, thus two. */
187 /* Mixing channel index. */
190 /* Left and right channel
191 ** are in global mixbuffer, alternating. */
193 rightout = mixbuffer+1;
196 /* Determine end, for left channel only
197 ** (right channel is implicit). */
198 leftend = mixbuffer + SAMPLECOUNT*step;
200 /* Mix sounds into the mixing buffer.
201 ** Loop over step*SAMPLECOUNT
202 ** that is 512 values for two channels.
204 while (leftout != leftend)
206 /* Reset left/right value. */
210 /* Love thy L2 cache - made this a loop.
211 ** Now more channels could be set at compile time
212 ** as well. Thus loop those channels.
214 for(chan=0; chan < NUM_CHANNELS; chan++)
216 /* Check channel, if active. */
219 /* Get the raw data from the channel. */
220 sample = *channels[ chan ];
221 /* Add left and right part
222 ** for this channel (sound)
223 ** to the current data.
224 ** Adjust volume accordingly.
226 dl += channelleftvol_lookup[ chan ][sample];
227 dr += channelrightvol_lookup[ chan ][sample];
228 /* Increment index ??? */
229 channelstepremainder[ chan ] += channelstep[ chan ];
230 /* MSB is next sample??? */
231 channels[ chan ] += channelstepremainder[ chan ] >> 16;
232 /* Limit to LSB??? */
233 channelstepremainder[ chan ] &= 65536-1;
235 /* Check whether we are done. */
236 if (channels[ chan ] >= channelsend[ chan ])
237 channels[ chan ] = 0;
241 /* Clamp to range. */
244 else if (dl < -0x8000)
248 else if (dr < -0x8000)
254 /* Increment current pointers in mixbuffer. */
275 void I_SubmitSound(void)
278 write(audio_fd, mixbuffer, MIXBUFFERSIZE);
281 void I_ShutdownSound(void)
289 void I_SetChannels(void)
291 /* Init internal lookups (raw data, mixing buffer, channels).
292 ** This function sets up internal lookups used during
293 ** the mixing process.
298 int *steptablemid = steptable + 128;
300 /* This table provides step widths for pitch parameters.
301 ** I fail to see that this is currently used. */
302 for (i=-128 ; i<128 ; i++)
303 steptablemid[i] = (int)(pow(2.0, (i/64.0))*65536.0);
305 /* Generates volume lookup tables
306 ** which also turn the unsigned samples
307 ** into signed samples.
309 for (i=0 ; i<128 ; i++)
310 for (j=0 ; j<256 ; j++)
311 vol_lookup[i*256+j] = (i*(j-128)*256)/127;
314 int I_GetSfxLumpNum(sfxinfo_t *sfxinfo)
317 sprintf(namebuf, "ds%s", sfxinfo->name);
318 return W_GetNumForName(namebuf);
321 /* This function adds a sound to the
322 ** list of currently active sounds,
323 ** which is maintained as a given number
324 ** (eight, usually) of internal channels.
328 addsfx(int id, int vol, int step, int sep)
330 static unsigned short handlenums = 0;
333 int oldest = gametic;
339 /* Chainsaw troubles.
340 ** Play these sound effects only one at a time. */
341 if ( id == sfx_sawup ||
348 /* Loop all channels, check. */
349 for (i=0 ; i < NUM_CHANNELS ; i++)
351 /* Active and using the same SFX? */
352 if( (channels[i]) && (channelids[i] == id) )
356 /* We are sure that iff,
357 ** there will only be one. */
363 /* Loop all channels to find oldest SFX. */
364 for (i=0 ; (i<NUM_CHANNELS) && (channels[i]) ; i++)
366 if(channelstart[i] < oldest)
369 oldest = channelstart[i];
373 /* Tales from the cryptic.
374 ** If we found a channel, fine.
375 ** If not, we simply overwrite the first one, 0.
376 ** Probably only happens at startup.
378 if (i == NUM_CHANNELS)
383 /* Okay, in the less recent channel,
384 ** we will handle the new SFX.
385 ** Set pointer to raw data.
387 channels[slot] = (uchar*) S_sfx[id].data;
388 /* Set pointer to end of raw data. */
389 channelsend[slot] = channels[slot] + lengths[id];
391 /* Reset current handle number, limited to 0..100. */
395 /* Assign current handle number.
396 ** Preserved so sounds could be stopped (unused).
398 channelhandles[slot] = rc = handlenums++;
401 ** Kinda getting the impression this is never used.
403 channelstep[slot] = step;
405 channelstepremainder[slot] = 0;
406 /* Should be gametic, I presume. */
407 channelstart[slot] = gametic;
409 /* Separation, that is, orientation/stereo.
410 ** range is : 1 - 256
414 /* Per left/right channel.
416 ** adjust volume properly.
418 leftvol = vol - ((vol*sep*sep) >> 16); // /(256*256);
420 rightvol = vol - ((vol*sep*sep) >> 16);
422 /* Sanity check, clamp volume. */
423 if (rightvol < 0 || rightvol > 127)
424 I_Error("rightvol out of bounds");
425 if (leftvol < 0 || leftvol > 127)
426 I_Error("leftvol out of bounds");
428 /* Get the proper lookup table piece
429 ** for this volume level???
431 channelleftvol_lookup[slot] = &vol_lookup[leftvol*256];
432 channelrightvol_lookup[slot] = &vol_lookup[rightvol*256];
434 /* Preserve sound SFX id,
435 ** e.g. for avoiding duplicates of chainsaw.
436 channelids[slot] = id;
442 int I_StartSound(int id, int vol, int sep, int pitch, int priority)
445 id = addsfx(id, vol, steptable[pitch], sep);
449 void I_StopSound(int handle)
452 // printf("PORTME i_sound.c I_StopSound\n");
455 int I_SoundIsPlaying(int handle)
458 return gametic < handle;
461 void I_UpdateSoundParams(int handle, int vol, int sep, int pitch)
463 /* I fail to see that this is used.
464 ** Would be using the handle to identify
465 ** on which channel the sound might be active,
466 ** and resetting the channel parameters.
468 USED(handle, vol, sep, pitch);
471 void I_InitMusic(void)
473 // printf("PORTME i_sound.c I_InitMusic\n");
476 void I_ShutdownMusic(void)
478 // printf("PORTME i_sound.c I_ShutdownMusic\n");
481 void I_SetMusicVolume(int volume)
484 // printf("PORTME i_sound.c I_SetMusicVolume\n");
487 void I_PauseSong(int handle)
490 // printf("PORTME i_sound.c I_PauseSong\n");
493 void I_ResumeSong(int handle)
496 // printf("PORTME i_sound.c I_ResumeSong\n");
499 int I_RegisterSong(void *data)
502 // printf("PORTME i_sound.c I_RegisterSong\n");
506 void I_PlaySong(int handle, int looping)
508 USED(handle, looping);
509 // printf("PORTME i_sound.c I_PlaySong\n");
512 void I_StopSong(int handle)
515 // printf("PORTME i_sound.c I_StopSong\n");
518 void I_UnRegisterSong(int handle)
521 // printf("PORTME i_sound.c I_UnregisterSong\n");