Rev 374 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 374 | Rev 376 | ||
---|---|---|---|
1 | // Emacs style mode select -*- C++ -*- |
1 | // Emacs style mode select -*- C++ -*- |
2 | //----------------------------------------------------------------------------- |
2 | //----------------------------------------------------------------------------- |
3 | // |
3 | // |
4 | // $Id:$ |
4 | // $Id:$ |
5 | // |
5 | // |
6 | // Copyright (C) 1993-1996 by id Software, Inc. |
6 | // Copyright (C) 1993-1996 by id Software, Inc. |
7 | // |
7 | // |
8 | // This source is available for distribution and/or modification |
8 | // This source is available for distribution and/or modification |
9 | // only under the terms of the DOOM Source Code License as |
9 | // only under the terms of the DOOM Source Code License as |
10 | // published by id Software. All rights reserved. |
10 | // published by id Software. All rights reserved. |
11 | // |
11 | // |
12 | // The source is distributed in the hope that it will be useful, |
12 | // The source is distributed in the hope that it will be useful, |
13 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License |
14 | // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License |
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 | //----------------------------------------------------------------------------- |
23 | 23 | ||
24 | static const char |
24 | static const char |
25 | rcsid[] = "$Id: i_unix.c,v 1.5 1997/02/03 22:45:10 b1 Exp $"; |
25 | rcsid[] = "$Id: i_unix.c,v 1.5 1997/02/03 22:45:10 b1 Exp $"; |
26 | 26 | ||
27 | #include |
27 | #include |
28 | #include |
28 | #include |
29 | #include |
29 | #include |
30 | 30 | ||
31 | #include |
31 | #include |
32 | 32 | ||
33 | #include |
33 | #include |
34 | 34 | ||
35 | #include |
35 | #include |
36 | 36 | ||
37 | // Timer stuff. Experimental. |
37 | // Timer stuff. Experimental. |
38 | #include |
38 | #include |
39 | #include |
39 | #include |
40 | 40 | ||
41 | #include "z_zone.h" |
41 | #include "z_zone.h" |
42 | 42 | ||
43 | #include "i_system.h" |
43 | #include "i_system.h" |
44 | #include "i_sound.h" |
44 | #include "i_sound.h" |
45 | #include "m_argv.h" |
45 | #include "m_argv.h" |
46 | #include "m_misc.h" |
46 | #include "m_misc.h" |
47 | #include "w_wad.h" |
47 | #include "w_wad.h" |
48 | 48 | ||
49 | #include "doomdef.h" |
49 | #include "doomdef.h" |
50 | 50 | ||
51 | #include "kolibri.h" |
51 | #include "kolibri.h" |
52 | #include "sound.h" |
52 | #include "sound.h" |
53 | 53 | ||
54 | // The number of internal mixing channels, |
54 | // The number of internal mixing channels, |
55 | // the samples calculated for each mixing step, |
55 | // the samples calculated for each mixing step, |
56 | // the size of the 16bit, 2 hardware channel (stereo) |
56 | // the size of the 16bit, 2 hardware channel (stereo) |
57 | // mixing buffer, and the samplerate of the raw data. |
57 | // mixing buffer, and the samplerate of the raw data. |
58 | 58 | ||
59 | 59 | ||
60 | // Needed for calling the actual sound output. |
60 | // Needed for calling the actual sound output. |
61 | #define SAMPLECOUNT 1024 |
61 | #define SAMPLECOUNT 1024 |
62 | #define NUM_CHANNELS 16 |
62 | #define NUM_CHANNELS 16 |
63 | // It is 2 for 16bit, and 2 for two channels. |
63 | // It is 2 for 16bit, and 2 for two channels. |
64 | //#define BUFMUL 4 |
64 | //#define BUFMUL 4 |
65 | //#define MIXBUFFERSIZE (SAMPLECOUNT*BUFMUL) |
65 | //#define MIXBUFFERSIZE (SAMPLECOUNT*BUFMUL) |
66 | 66 | ||
67 | #define SAMPLERATE 11025 // Hz |
67 | #define SAMPLERATE 11025 // Hz |
68 | #define SAMPLESIZE 2 // 16bit |
68 | #define SAMPLESIZE 2 // 16bit |
69 | 69 | ||
70 | // The actual lengths of all sound effects. |
70 | // The actual lengths of all sound effects. |
71 | int lengths[NUMSFX]; |
71 | int lengths[NUMSFX]; |
72 | 72 | ||
73 | // The actual output device. |
73 | // The actual output device. |
74 | int audio_fd; |
74 | int audio_fd; |
75 | 75 | ||
76 | // The global mixing buffer. |
76 | // The global mixing buffer. |
77 | // Basically, samples from all active internal channels |
77 | // Basically, samples from all active internal channels |
78 | // are modifed and added, and stored in the buffer |
78 | // are modifed and added, and stored in the buffer |
79 | // that is submitted to the audio device. |
79 | // that is submitted to the audio device. |
80 | signed short *mixbuffer; |
80 | signed short *mixbuffer; |
81 | 81 | ||
82 | // The channel step amount... |
82 | // The channel step amount... |
83 | unsigned int channelstep[NUM_CHANNELS]; |
83 | unsigned int channelstep[NUM_CHANNELS]; |
84 | // ... and a 0.16 bit remainder of last step. |
84 | // ... and a 0.16 bit remainder of last step. |
85 | unsigned int channelstepremainder[NUM_CHANNELS]; |
85 | unsigned int channelstepremainder[NUM_CHANNELS]; |
86 | 86 | ||
87 | 87 | ||
88 | // The channel data pointers, start and end. |
88 | // The channel data pointers, start and end. |
89 | unsigned char* channels[NUM_CHANNELS]; |
89 | unsigned char* channels[NUM_CHANNELS]; |
90 | unsigned char* channelsend[NUM_CHANNELS]; |
90 | unsigned char* channelsend[NUM_CHANNELS]; |
91 | 91 | ||
92 | 92 | ||
93 | // Time/gametic that the channel started playing, |
93 | // Time/gametic that the channel started playing, |
94 | // used to determine oldest, which automatically |
94 | // used to determine oldest, which automatically |
95 | // has lowest priority. |
95 | // has lowest priority. |
96 | // In case number of active sounds exceeds |
96 | // In case number of active sounds exceeds |
97 | // available channels. |
97 | // available channels. |
98 | int channelstart[NUM_CHANNELS]; |
98 | int channelstart[NUM_CHANNELS]; |
99 | 99 | ||
100 | // The sound in channel handles, |
100 | // The sound in channel handles, |
101 | // determined on registration, |
101 | // determined on registration, |
102 | // might be used to unregister/stop/modify, |
102 | // might be used to unregister/stop/modify, |
103 | // currently unused. |
103 | // currently unused. |
104 | int channelhandles[NUM_CHANNELS]; |
104 | int channelhandles[NUM_CHANNELS]; |
105 | 105 | ||
106 | // SFX id of the playing sound effect. |
106 | // SFX id of the playing sound effect. |
107 | // Used to catch duplicates (like chainsaw). |
107 | // Used to catch duplicates (like chainsaw). |
108 | int channelids[NUM_CHANNELS]; |
108 | int channelids[NUM_CHANNELS]; |
109 | 109 | ||
110 | // Pitch to stepping lookup, unused. |
110 | // Pitch to stepping lookup, unused. |
111 | int steptable[256]; |
111 | int steptable[256]; |
112 | 112 | ||
113 | // Volume lookups. |
113 | // Volume lookups. |
114 | int vol_lookup[128*256]; |
114 | int vol_lookup[128*256]; |
115 | 115 | ||
116 | // Hardware left and right channel volume lookup. |
116 | // Hardware left and right channel volume lookup. |
117 | int* channelleftvol_lookup[NUM_CHANNELS]; |
117 | int* channelleftvol_lookup[NUM_CHANNELS]; |
118 | int* channelrightvol_lookup[NUM_CHANNELS]; |
118 | int* channelrightvol_lookup[NUM_CHANNELS]; |
119 | 119 | ||
120 | 120 | ||
121 | // |
121 | // |
122 | // This function loads the sound data from the WAD lump, |
122 | // This function loads the sound data from the WAD lump, |
123 | // for single sound. |
123 | // for single sound. |
124 | // |
124 | // |
125 | void* getsfx (char* sfxname, int* len) |
125 | void* getsfx (char* sfxname, int* len) |
126 | { |
126 | { |
127 | unsigned char* sfx; |
127 | unsigned char* sfx; |
128 | unsigned char* paddedsfx; |
128 | unsigned char* paddedsfx; |
129 | int i; |
129 | int i; |
130 | int size; |
130 | int size; |
131 | int paddedsize; |
131 | int paddedsize; |
132 | char name[20]; |
132 | char name[20]; |
133 | int sfxlump; |
133 | int sfxlump; |
134 | 134 | ||
135 | 135 | ||
136 | // Get the sound data from the WAD, allocate lump |
136 | // Get the sound data from the WAD, allocate lump |
137 | // in zone memory. |
137 | // in zone memory. |
138 | sprintf(name, "ds%s", sfxname); |
138 | sprintf(name, "ds%s", sfxname); |
139 | 139 | ||
140 | // Now, there is a severe problem with the |
140 | // Now, there is a severe problem with the |
141 | // sound handling, in it is not (yet/anymore) |
141 | // sound handling, in it is not (yet/anymore) |
142 | // gamemode aware. That means, sounds from |
142 | // gamemode aware. That means, sounds from |
143 | // DOOM II will be requested even with DOOM |
143 | // DOOM II will be requested even with DOOM |
144 | // shareware. |
144 | // shareware. |
145 | // The sound list is wired into sounds.c, |
145 | // The sound list is wired into sounds.c, |
146 | // which sets the external variable. |
146 | // which sets the external variable. |
147 | // I do not do runtime patches to that |
147 | // I do not do runtime patches to that |
148 | // variable. Instead, we will use a |
148 | // variable. Instead, we will use a |
149 | // default sound for replacement. |
149 | // default sound for replacement. |
150 | if ( W_CheckNumForName(name) == -1 ) |
150 | if ( W_CheckNumForName(name) == -1 ) |
151 | sfxlump = W_GetNumForName("dspistol"); |
151 | sfxlump = W_GetNumForName("dspistol"); |
152 | else |
152 | else |
153 | sfxlump = W_GetNumForName(name); |
153 | sfxlump = W_GetNumForName(name); |
154 | 154 | ||
155 | size = W_LumpLength( sfxlump ); |
155 | size = W_LumpLength( sfxlump ); |
156 | 156 | ||
157 | // Debug. |
157 | // Debug. |
158 | // fprintf( stderr, "." ); |
158 | // fprintf( stderr, "." ); |
159 | //fprintf( stderr, " -loading %s (lump %d, %d bytes)\n", |
159 | //fprintf( stderr, " -loading %s (lump %d, %d bytes)\n", |
160 | // sfxname, sfxlump, size ); |
160 | // sfxname, sfxlump, size ); |
161 | //fflush( stderr ); |
161 | //fflush( stderr ); |
162 | 162 | ||
163 | sfx = (unsigned char*)W_CacheLumpNum( sfxlump, PU_STATIC ); |
163 | sfx = (unsigned char*)W_CacheLumpNum( sfxlump, PU_STATIC ); |
164 | 164 | ||
165 | // Pads the sound effect out to the mixing buffer size. |
165 | // Pads the sound effect out to the mixing buffer size. |
166 | // The original realloc would interfere with zone memory. |
166 | // The original realloc would interfere with zone memory. |
167 | paddedsize = ((size-8 + (SAMPLECOUNT-1)) / SAMPLECOUNT) * SAMPLECOUNT; |
167 | paddedsize = ((size-8 + (SAMPLECOUNT-1)) / SAMPLECOUNT) * SAMPLECOUNT; |
168 | 168 | ||
169 | // Allocate from zone memory. |
169 | // Allocate from zone memory. |
170 | paddedsfx = (unsigned char*)Z_Malloc( paddedsize+8, PU_STATIC, 0 ); |
170 | paddedsfx = (unsigned char*)Z_Malloc( paddedsize+8, PU_STATIC, 0 ); |
171 | // ddt: (unsigned char *) realloc(sfx, paddedsize+8); |
171 | // ddt: (unsigned char *) realloc(sfx, paddedsize+8); |
172 | // This should interfere with zone memory handling, |
172 | // This should interfere with zone memory handling, |
173 | // which does not kick in in the soundserver. |
173 | // which does not kick in in the soundserver. |
174 | 174 | ||
175 | // Now copy and pad. |
175 | // Now copy and pad. |
176 | memcpy( paddedsfx, sfx, size ); |
176 | memcpy( paddedsfx, sfx, size ); |
177 | for (i=size ; i |
177 | for (i=size ; i |
178 | paddedsfx[i] = 128; |
178 | paddedsfx[i] = 128; |
179 | 179 | ||
180 | // Remove the cached lump. |
180 | // Remove the cached lump. |
181 | Z_Free( sfx ); |
181 | Z_Free( sfx ); |
182 | 182 | ||
183 | // Preserve padded length. |
183 | // Preserve padded length. |
184 | *len = paddedsize; |
184 | *len = paddedsize; |
185 | 185 | ||
186 | // Return allocated padded data. |
186 | // Return allocated padded data. |
187 | return (void *) (paddedsfx + 8); |
187 | return (void *) (paddedsfx + 8); |
188 | } |
188 | } |
189 | 189 | ||
190 | // |
190 | // |
191 | // This function adds a sound to the |
191 | // This function adds a sound to the |
192 | // list of currently active sounds, |
192 | // list of currently active sounds, |
193 | // which is maintained as a given number |
193 | // which is maintained as a given number |
194 | // (eight, usually) of internal channels. |
194 | // (eight, usually) of internal channels. |
195 | // Returns a handle. |
195 | // Returns a handle. |
196 | // |
196 | // |
197 | 197 | ||
198 | static unsigned short handlenums = 0; |
198 | static unsigned short handlenums = 0; |
199 | 199 | ||
200 | int addsfx(int sfxid, int volume, int step, int seperation) |
200 | int addsfx(int sfxid, int volume, int step, int seperation) |
201 | { |
201 | { |
202 | 202 | ||
203 | int i; |
203 | int i; |
204 | int rc = -1; |
204 | int rc = -1; |
205 | 205 | ||
206 | int oldest = gametic; |
206 | int oldest = gametic; |
207 | int oldestnum = 0; |
207 | int oldestnum = 0; |
208 | int slot; |
208 | int slot; |
209 | 209 | ||
210 | int rightvol; |
210 | int rightvol; |
211 | int leftvol; |
211 | int leftvol; |
212 | 212 | ||
213 | // Chainsaw troubles. |
213 | // Chainsaw troubles. |
214 | // Play these sound effects only one at a time. |
214 | // Play these sound effects only one at a time. |
215 | if ( sfxid == sfx_sawup |
215 | if ( sfxid == sfx_sawup |
216 | || sfxid == sfx_sawidl |
216 | || sfxid == sfx_sawidl |
217 | || sfxid == sfx_sawful |
217 | || sfxid == sfx_sawful |
218 | || sfxid == sfx_sawhit |
218 | || sfxid == sfx_sawhit |
219 | || sfxid == sfx_stnmov |
219 | || sfxid == sfx_stnmov |
220 | || sfxid == sfx_pistol ) |
220 | || sfxid == sfx_pistol ) |
221 | { |
221 | { |
222 | // Loop all channels, check. |
222 | // Loop all channels, check. |
223 | for (i=0 ; i |
223 | for (i=0 ; i |
224 | { |
224 | { |
225 | // Active, and using the same SFX? |
225 | // Active, and using the same SFX? |
226 | if ( (channels[i]) |
226 | if ( (channels[i]) |
227 | && (channelids[i] == sfxid) ) |
227 | && (channelids[i] == sfxid) ) |
228 | { |
228 | { |
229 | // Reset. |
229 | // Reset. |
230 | channels[i] = 0; |
230 | channels[i] = 0; |
231 | // We are sure that iff, |
231 | // We are sure that iff, |
232 | // there will only be one. |
232 | // there will only be one. |
233 | break; |
233 | break; |
234 | } |
234 | } |
235 | } |
235 | } |
236 | } |
236 | } |
237 | 237 | ||
238 | // Loop all channels to find oldest SFX. |
238 | // Loop all channels to find oldest SFX. |
239 | for (i=0; (i |
239 | for (i=0; (i |
240 | { |
240 | { |
241 | if (channelstart[i] < oldest) |
241 | if (channelstart[i] < oldest) |
242 | { |
242 | { |
243 | oldestnum = i; |
243 | oldestnum = i; |
244 | oldest = channelstart[i]; |
244 | oldest = channelstart[i]; |
245 | } |
245 | } |
246 | } |
246 | } |
247 | 247 | ||
248 | // Tales from the cryptic. |
248 | // Tales from the cryptic. |
249 | // If we found a channel, fine. |
249 | // If we found a channel, fine. |
250 | // If not, we simply overwrite the first one, 0. |
250 | // If not, we simply overwrite the first one, 0. |
251 | // Probably only happens at startup. |
251 | // Probably only happens at startup. |
252 | if (i == NUM_CHANNELS) |
252 | if (i == NUM_CHANNELS) |
253 | slot = oldestnum; |
253 | slot = oldestnum; |
254 | else |
254 | else |
255 | slot = i; |
255 | slot = i; |
256 | 256 | ||
257 | // Okay, in the less recent channel, |
257 | // Okay, in the less recent channel, |
258 | // we will handle the new SFX. |
258 | // we will handle the new SFX. |
259 | // Set pointer to raw data. |
259 | // Set pointer to raw data. |
260 | channels[slot] = (unsigned char *) S_sfx[sfxid].data; |
260 | channels[slot] = (unsigned char *) S_sfx[sfxid].data; |
261 | // Set pointer to end of raw data. |
261 | // Set pointer to end of raw data. |
262 | channelsend[slot] = channels[slot] + lengths[sfxid]; |
262 | channelsend[slot] = channels[slot] + lengths[sfxid]; |
263 | 263 | ||
264 | // Reset current handle number, limited to 0..100. |
264 | // Reset current handle number, limited to 0..100. |
265 | if (!handlenums) |
265 | if (!handlenums) |
266 | handlenums = 100; |
266 | handlenums = 100; |
267 | 267 | ||
268 | // Assign current handle number. |
268 | // Assign current handle number. |
269 | // Preserved so sounds could be stopped (unused). |
269 | // Preserved so sounds could be stopped (unused). |
270 | channelhandles[slot] = rc = handlenums++; |
270 | channelhandles[slot] = rc = handlenums++; |
271 | 271 | ||
272 | channelstep[slot] = step; |
272 | channelstep[slot] = step; |
273 | 273 | ||
274 | channelstepremainder[slot] = 0; |
274 | channelstepremainder[slot] = 0; |
275 | // Should be gametic, I presume. |
275 | // Should be gametic, I presume. |
276 | channelstart[slot] = gametic; |
276 | channelstart[slot] = gametic; |
277 | 277 | ||
278 | // Separation, that is, orientation/stereo. |
278 | // Separation, that is, orientation/stereo. |
279 | // range is: 1 - 256 |
279 | // range is: 1 - 256 |
280 | seperation += 1; |
280 | seperation += 1; |
281 | 281 | ||
282 | volume *=7; |
282 | volume *=7; |
283 | // Per left/right channel. |
283 | // Per left/right channel. |
284 | // x^2 seperation, |
284 | // x^2 seperation, |
285 | // adjust volume properly. |
285 | // adjust volume properly. |
286 | leftvol = |
286 | leftvol = |
287 | volume - ((volume*seperation*seperation) >> 16); ///(256*256); |
287 | volume - ((volume*seperation*seperation) >> 16); ///(256*256); |
288 | seperation = seperation - 257; |
288 | seperation = seperation - 257; |
289 | rightvol = |
289 | rightvol = |
290 | volume - ((volume*seperation*seperation) >> 16); |
290 | volume - ((volume*seperation*seperation) >> 16); |
291 | 291 | ||
292 | // Sanity check, clamp volume. |
292 | // Sanity check, clamp volume. |
293 | if (rightvol < 0 || rightvol > 127) |
293 | if (rightvol < 0 || rightvol > 127) |
294 | { |
294 | { |
295 | printf("rightvol out of bounds\n\r"); |
295 | printf("rightvol out of bounds\n\r"); |
296 | rightvol = 0; |
296 | rightvol = 0; |
297 | 297 | ||
298 | } |
298 | } |
299 | 299 | ||
300 | if (leftvol < 0 || leftvol > 127) |
300 | if (leftvol < 0 || leftvol > 127) |
301 | { |
301 | { |
302 | printf("leftvol out of bounds\n\r"); |
302 | printf("leftvol out of bounds\n\r"); |
303 | leftvol=0; |
303 | leftvol=0; |
304 | } |
304 | } |
305 | 305 | ||
306 | // Get the proper lookup table piece |
306 | // Get the proper lookup table piece |
307 | // for this volume level??? |
307 | // for this volume level??? |
308 | channelleftvol_lookup[slot] = &vol_lookup[leftvol*256]; |
308 | channelleftvol_lookup[slot] = &vol_lookup[leftvol*256]; |
309 | channelrightvol_lookup[slot] = &vol_lookup[rightvol*256]; |
309 | channelrightvol_lookup[slot] = &vol_lookup[rightvol*256]; |
310 | 310 | ||
311 | // Preserve sound SFX id, |
311 | // Preserve sound SFX id, |
312 | // e.g. for avoiding duplicates of chainsaw. |
312 | // e.g. for avoiding duplicates of chainsaw. |
313 | channelids[slot] = sfxid; |
313 | channelids[slot] = sfxid; |
314 | 314 | ||
315 | // You tell me. |
315 | // You tell me. |
316 | return rc; |
316 | return rc; |
317 | } |
317 | } |
318 | 318 | ||
319 | // |
319 | // |
320 | // SFX API |
320 | // SFX API |
321 | // Note: this was called by S_Init. |
321 | // Note: this was called by S_Init. |
322 | // However, whatever they did in the |
322 | // However, whatever they did in the |
323 | // old DPMS based DOS version, this |
323 | // old DPMS based DOS version, this |
324 | // were simply dummies in the Linux |
324 | // were simply dummies in the Linux |
325 | // version. |
325 | // version. |
326 | // See soundserver initdata(). |
326 | // See soundserver initdata(). |
327 | // |
327 | // |
328 | void I_SetChannels() |
328 | void I_SetChannels() |
329 | { |
329 | { |
330 | // Init internal lookups (raw data, mixing buffer, channels). |
330 | // Init internal lookups (raw data, mixing buffer, channels). |
331 | // This function sets up internal lookups used during |
331 | // This function sets up internal lookups used during |
332 | // the mixing process. |
332 | // the mixing process. |
333 | int i; |
333 | int i; |
334 | int j; |
334 | int j; |
335 | 335 | ||
336 | int* steptablemid = steptable + 128; |
336 | int* steptablemid = steptable + 128; |
337 | 337 | ||
338 | // Okay, reset internal mixing channels to zero. |
338 | // Okay, reset internal mixing channels to zero. |
339 | for (i=0; i |
339 | for (i=0; i |
340 | { |
340 | { |
341 | channels[i] = 0; |
341 | channels[i] = 0; |
342 | } |
342 | } |
343 | 343 | ||
344 | for (i=-128 ; i<128 ; i++) |
344 | for (i=-128 ; i<128 ; i++) |
345 | steptablemid[i] = (int)(pow(2.0, (i/64.0))*65536.0); |
345 | steptablemid[i] = (int)(pow(2.0, (i/64.0))*65536.0); |
346 | 346 | ||
347 | // Generates volume lookup tables |
347 | // Generates volume lookup tables |
348 | // which also turn the unsigned samples |
348 | // which also turn the unsigned samples |
349 | // into signed samples. |
349 | // into signed samples. |
350 | for (i=0 ; i<128 ; i++) |
350 | for (i=0 ; i<128 ; i++) |
351 | for (j=0 ; j<256 ; j++) |
351 | for (j=0 ; j<256 ; j++) |
352 | vol_lookup[i*256+j] = (i*(j-128)*256)/127; |
352 | vol_lookup[i*256+j] = (i*(j-128)*256)/127; |
353 | } |
353 | } |
354 | 354 | ||
355 | 355 | ||
356 | void I_SetSfxVolume(int volume) |
356 | void I_SetSfxVolume(int volume) |
357 | { |
357 | { |
358 | // Identical to DOS. |
358 | // Identical to DOS. |
359 | // Basically, this should propagate |
359 | // Basically, this should propagate |
360 | // the menu/config file setting |
360 | // the menu/config file setting |
361 | // to the state variable used in |
361 | // to the state variable used in |
362 | // the mixing. |
362 | // the mixing. |
363 | snd_SfxVolume = volume; |
363 | snd_SfxVolume = volume; |
364 | } |
364 | } |
365 | 365 | ||
366 | // MUSIC API - dummy. Some code from DOS version. |
366 | // MUSIC API - dummy. Some code from DOS version. |
367 | void I_SetMusicVolume(int volume) |
367 | void I_SetMusicVolume(int volume) |
368 | { |
368 | { |
369 | // Internal state variable. |
369 | // Internal state variable. |
370 | snd_MusicVolume = volume; |
370 | snd_MusicVolume = volume; |
371 | } |
371 | } |
372 | 372 | ||
373 | 373 | ||
374 | // |
374 | // |
375 | // Retrieve the raw data lump index |
375 | // Retrieve the raw data lump index |
376 | // for a given SFX name. |
376 | // for a given SFX name. |
377 | // |
377 | // |
378 | int I_GetSfxLumpNum(sfxinfo_t* sfx) |
378 | int I_GetSfxLumpNum(sfxinfo_t* sfx) |
379 | { |
379 | { |
380 | char namebuf[9]; |
380 | char namebuf[9]; |
381 | sprintf(namebuf, "ds%s", sfx->name); |
381 | sprintf(namebuf, "ds%s", sfx->name); |
382 | return W_GetNumForName(namebuf); |
382 | return W_GetNumForName(namebuf); |
383 | } |
383 | } |
384 | 384 | ||
385 | // |
385 | // |
386 | // Starting a sound means adding it |
386 | // Starting a sound means adding it |
387 | // to the current list of active sounds |
387 | // to the current list of active sounds |
388 | // in the internal channels. |
388 | // in the internal channels. |
389 | // As the SFX info struct contains |
389 | // As the SFX info struct contains |
390 | // e.g. a pointer to the raw data, |
390 | // e.g. a pointer to the raw data, |
391 | // it is ignored. |
391 | // it is ignored. |
392 | // As our sound handling does not handle |
392 | // As our sound handling does not handle |
393 | // priority, it is ignored. |
393 | // priority, it is ignored. |
394 | // Pitching (that is, increased speed of playback) |
394 | // Pitching (that is, increased speed of playback) |
395 | // |
395 | // |
396 | int I_StartSound(int id, int vol, int sep, |
396 | int I_StartSound(int id, int vol, int sep, |
397 | int pitch, int priority ) |
397 | int pitch, int priority ) |
398 | { |
398 | { |
399 | // Returns a handle (not used). |
399 | // Returns a handle (not used). |
400 | id = addsfx( id, vol, steptable[pitch], sep ); |
400 | id = addsfx( id, vol, steptable[pitch], sep ); |
401 | return id; |
401 | return id; |
402 | } |
402 | } |
403 | 403 | ||
404 | void I_StopSound (int handle) |
404 | void I_StopSound (int handle) |
405 | { |
405 | { |
406 | // You need the handle returned by StartSound. |
406 | // You need the handle returned by StartSound. |
407 | // Would be looping all channels, |
407 | // Would be looping all channels, |
408 | // tracking down the handle, |
408 | // tracking down the handle, |
409 | // an setting the channel to zero. |
409 | // an setting the channel to zero. |
410 | 410 | ||
411 | // UNUSED. |
411 | // UNUSED. |
412 | handle = 0; |
412 | handle = 0; |
413 | } |
413 | } |
414 | 414 | ||
415 | 415 | ||
416 | int I_SoundIsPlaying(int handle) |
416 | int I_SoundIsPlaying(int handle) |
417 | { |
417 | { |
418 | // Ouch. |
418 | // Ouch. |
419 | return gametic < handle; |
419 | return gametic < handle; |
420 | } |
420 | } |
421 | 421 | ||
422 | // |
422 | // |
423 | // This function loops all active (internal) sound |
423 | // This function loops all active (internal) sound |
424 | // channels, retrieves a given number of samples |
424 | // channels, retrieves a given number of samples |
425 | // from the raw sound data, modifies it according |
425 | // from the raw sound data, modifies it according |
426 | // to the current (internal) channel parameters, |
426 | // to the current (internal) channel parameters, |
427 | // mixes the per channel samples into the global |
427 | // mixes the per channel samples into the global |
428 | // mixbuffer, clamping it to the allowed range, |
428 | // mixbuffer, clamping it to the allowed range, |
429 | // and sets up everything for transferring the |
429 | // and sets up everything for transferring the |
430 | // contents of the mixbuffer to the (two) |
430 | // contents of the mixbuffer to the (two) |
431 | // hardware channels (left and right, that is). |
431 | // hardware channels (left and right, that is). |
432 | // |
432 | // |
433 | // This function currently supports only 16bit. |
433 | // This function currently supports only 16bit. |
434 | // |
434 | // |
435 | 435 | ||
436 | extern SNDBUF hMixBuff; |
436 | extern SNDBUF hMixBuff; |
437 | extern unsigned int mix_offset; |
437 | extern unsigned int mix_offset; |
438 | extern int mix_size; |
438 | extern int mix_size; |
439 | 439 | ||
440 | void I_UpdateSound( void ) |
440 | void I_UpdateSound( void ) |
441 | { |
441 | { |
442 | 442 | ||
443 | // Mix current sound data. |
443 | // Mix current sound data. |
444 | // Data, from raw sound, for right and left. |
444 | // Data, from raw sound, for right and left. |
445 | register unsigned int sample; |
445 | register unsigned int sample; |
446 | register int dl; |
446 | register int dl; |
447 | register int dr; |
447 | register int dr; |
448 | 448 | ||
449 | // Pointers in global mixbuffer, left, right, end. |
449 | // Pointers in global mixbuffer, left, right, end. |
450 | signed short* leftout; |
450 | signed short* leftout; |
451 | signed short* rightout; |
451 | signed short* rightout; |
452 | // signed short* leftend; |
452 | // signed short* leftend; |
453 | // Step in mixbuffer, left and right, thus two. |
453 | // Step in mixbuffer, left and right, thus two. |
454 | int step; |
454 | int step; |
455 | 455 | ||
456 | // Mixing channel index. |
456 | // Mixing channel index. |
457 | int chan; |
457 | int chan; |
458 | int i; |
458 | int i; |
459 | int flags; |
- | |
460 | int size = 0; |
- | |
461 | 459 | ||
462 | // Left and right channel |
460 | // Left and right channel |
463 | // are in global mixbuffer, alternating. |
461 | // are in global mixbuffer, alternating. |
464 | leftout = mixbuffer; |
462 | leftout = mixbuffer; |
465 | rightout = mixbuffer+1; |
463 | rightout = mixbuffer+1; |
466 | step = 2; |
464 | step = 2; |
467 | 465 | ||
468 | // Determine end, for left channel only |
466 | // Determine end, for left channel only |
469 | // (right channel is implicit). |
467 | // (right channel is implicit). |
470 | // leftend = mixbuffer + SAMPLECOUNT*step; |
468 | // leftend = mixbuffer + SAMPLECOUNT*step; |
471 | 469 | ||
472 | // Mix sounds into the mixing buffer. |
470 | // Mix sounds into the mixing buffer. |
473 | // Loop over step*SAMPLECOUNT, |
471 | // Loop over step*SAMPLECOUNT, |
474 | // that is 512 values for two channels. |
472 | // that is 512 values for two channels. |
475 | for (i=0; i < mix_size/4; i++) |
473 | for (i=0; i < mix_size/4; i++) |
476 | { |
474 | { |
477 | // Reset left/right value. |
475 | // Reset left/right value. |
478 | dl = 0; |
476 | dl = 0; |
479 | dr = 0; |
477 | dr = 0; |
480 | 478 | ||
481 | // Love thy L2 chache - made this a loop. |
479 | // Love thy L2 chache - made this a loop. |
482 | // Now more channels could be set at compile time |
480 | // Now more channels could be set at compile time |
483 | // as well. Thus loop those channels. |
481 | // as well. Thus loop those channels. |
484 | // flags=0; |
- | |
485 | 482 | ||
486 | for ( chan = 0; chan < NUM_CHANNELS; chan++ ) |
483 | for ( chan = 0; chan < NUM_CHANNELS; chan++ ) |
487 | { |
484 | { |
488 | // Check channel, if active. |
485 | // Check channel, if active. |
489 | if (channels[ chan ]) |
486 | if (channels[ chan ]) |
490 | { |
487 | { |
491 | // flags=1; |
- | |
492 | - | ||
493 | // Get the raw data from the channel. |
488 | // Get the raw data from the channel. |
494 | sample = *channels[ chan ]; |
489 | sample = *channels[ chan ]; |
495 | // Add left and right part |
490 | // Add left and right part |
496 | // for this channel (sound) |
491 | // for this channel (sound) |
497 | // to the current data. |
492 | // to the current data. |
498 | // Adjust volume accordingly. |
493 | // Adjust volume accordingly. |
499 | dl += channelleftvol_lookup[ chan ][sample]; |
494 | dl += channelleftvol_lookup[ chan ][sample]; |
500 | dr += channelrightvol_lookup[ chan ][sample]; |
495 | dr += channelrightvol_lookup[ chan ][sample]; |
501 | 496 | ||
502 | channelstepremainder[ chan ] += channelstep[ chan ]; |
497 | channelstepremainder[ chan ] += channelstep[ chan ]; |
503 | 498 | ||
504 | channels[ chan ] += channelstepremainder[ chan ] >> 16; |
499 | channels[ chan ] += channelstepremainder[ chan ] >> 16; |
505 | 500 | ||
506 | channelstepremainder[ chan ] &= 65536-1; |
501 | channelstepremainder[ chan ] &= 65536-1; |
507 | 502 | ||
508 | // Check whether we are done. |
503 | // Check whether we are done. |
509 | if (channels[ chan ] >= channelsend[ chan ]) |
504 | if (channels[ chan ] >= channelsend[ chan ]) |
510 | channels[ chan ] = 0; |
505 | channels[ chan ] = 0; |
511 | } |
506 | } |
512 | } |
507 | } |
513 | 508 | ||
514 | // Clamp to range. Left hardware channel. |
509 | // Clamp to range. Left hardware channel. |
515 | // Has been char instead of short. |
510 | // Has been char instead of short. |
516 | // if (dl > 127) *leftout = 127; |
511 | // if (dl > 127) *leftout = 127; |
517 | // else if (dl < -128) *leftout = -128; |
512 | // else if (dl < -128) *leftout = -128; |
518 | // else *leftout = dl; |
513 | // else *leftout = dl; |
519 | 514 | ||
520 | if (dl > 0x7fff) |
515 | if (dl > 0x7fff) |
521 | *leftout = 0x7fff; |
516 | *leftout = 0x7fff; |
522 | else if (dl < -0x8000) |
517 | else if (dl < -0x8000) |
523 | *leftout = -0x8000; |
518 | *leftout = -0x8000; |
524 | else |
519 | else |
525 | *leftout = dl; |
520 | *leftout = dl; |
526 | 521 | ||
527 | // Same for right hardware channel. |
522 | // Same for right hardware channel. |
528 | if (dr > 0x7fff) |
523 | if (dr > 0x7fff) |
529 | *rightout = 0x7fff; |
524 | *rightout = 0x7fff; |
530 | else if (dr < -0x8000) |
525 | else if (dr < -0x8000) |
531 | *rightout = -0x8000; |
526 | *rightout = -0x8000; |
532 | else |
527 | else |
533 | *rightout = dr; |
528 | *rightout = dr; |
534 | 529 | ||
535 | // Increment current pointers in mixbuffer. |
530 | // Increment current pointers in mixbuffer. |
536 | leftout += step; |
531 | leftout += step; |
537 | rightout += step; |
532 | rightout += step; |
538 | // if (flags) |
- | |
539 | // size+=4; |
- | |
540 | } |
533 | } |
541 | 534 | ||
542 | SetBuffer(hMixBuff,mixbuffer,mix_offset,mix_size); |
535 | SetBuffer(hMixBuff,mixbuffer,mix_offset,mix_size); |
543 | - | ||
544 | - | ||
545 | // WaveOut(hMixBuff,(char*)&mixbuffer[0],4096); |
- | |
546 | - | ||
547 | // if(size) |
- | |
548 | // { |
- | |
549 | // WaveOut(hMixBuff,(char*)&mixbuffer[0],size); |
- | |
550 | // SetBufferPos(hMixBuff, 0); |
- | |
551 | // SetBuffer(hMixBuff,(char*)&mixbuffer[0],mix_offset,4096); |
- | |
552 | // PlayBuffer(hMixBuff, PCM_SYNC); |
- | |
553 | // }; |
- | |
554 | } |
536 | } |
555 | 537 | ||
556 | 538 | ||
557 | // |
539 | // |
558 | // This would be used to write out the mixbuffer |
540 | // This would be used to write out the mixbuffer |
559 | // during each game loop update. |
541 | // during each game loop update. |
560 | // Updates sound buffer and audio device at runtime. |
542 | // Updates sound buffer and audio device at runtime. |
561 | // It is called during Timer interrupt with SNDINTR. |
543 | // It is called during Timer interrupt with SNDINTR. |
562 | // Mixing now done synchronous, and |
544 | // Mixing now done synchronous, and |
563 | // only output be done asynchronous? |
545 | // only output be done asynchronous? |
564 | // |
546 | // |
565 | //void I_SubmitSound(void) |
547 | //void I_SubmitSound(void) |
566 | //{ |
548 | //{ |
567 | // Write it to DSP device. |
549 | // Write it to DSP device. |
568 | // write(audio_fd, mixbuffer, SAMPLECOUNT*BUFMUL); |
550 | // write(audio_fd, mixbuffer, SAMPLECOUNT*BUFMUL); |
569 | //} |
551 | //} |
570 | 552 | ||
571 | 553 | ||
572 | void I_UpdateSoundParams(int handle, int vol, int sep, int pitch) |
554 | void I_UpdateSoundParams(int handle, int vol, int sep, int pitch) |
573 | { |
555 | { |
574 | // I fail too see that this is used. |
556 | // I fail too see that this is used. |
575 | // Would be using the handle to identify |
557 | // Would be using the handle to identify |
576 | // on which channel the sound might be active, |
558 | // on which channel the sound might be active, |
577 | // and resetting the channel parameters. |
559 | // and resetting the channel parameters. |
578 | 560 | ||
579 | // UNUSED. |
561 | // UNUSED. |
580 | handle = vol = sep = pitch = 0; |
562 | handle = vol = sep = pitch = 0; |
581 | } |
563 | } |
582 | 564 | ||
583 | extern volatile int sound_state; |
565 | extern volatile int sound_state; |
584 | 566 | ||
585 | void I_ShutdownSound(void) |
567 | void I_ShutdownSound(void) |
586 | { |
568 | { |
587 | sound_state=0; |
569 | sound_state=0; |
588 | return; |
570 | return; |
589 | } |
571 | } |
590 | 572 | ||
591 | void I_InitSound() |
573 | void I_InitSound() |
592 | { int i; |
574 | { int i; |
593 | 575 | ||
594 | printf("I_InitSound: "); |
576 | printf("I_InitSound: "); |
595 | 577 | ||
596 | for (i=1 ; i |
578 | for (i=1 ; i |
597 | { |
579 | { |
598 | // Alias? Example is the chaingun sound linked to pistol. |
580 | // Alias? Example is the chaingun sound linked to pistol. |
599 | if (!S_sfx[i].link) |
581 | if (!S_sfx[i].link) |
600 | { |
582 | { |
601 | // Load data from WAD file. |
583 | // Load data from WAD file. |
602 | S_sfx[i].data = getsfx( S_sfx[i].name, &lengths[i] ); |
584 | S_sfx[i].data = getsfx( S_sfx[i].name, &lengths[i] ); |
603 | } |
585 | } |
604 | else |
586 | else |
605 | { |
587 | { |
606 | // Previously loaded already? |
588 | // Previously loaded already? |
607 | S_sfx[i].data = S_sfx[i].link->data; |
589 | S_sfx[i].data = S_sfx[i].link->data; |
608 | lengths[i] = lengths[(S_sfx[i].link - S_sfx)/sizeof(sfxinfo_t)]; |
590 | lengths[i] = lengths[(S_sfx[i].link - S_sfx)/sizeof(sfxinfo_t)]; |
609 | } |
591 | } |
610 | } |
592 | } |
611 | 593 | ||
612 | printf( " pre-cached all sound data\n"); |
594 | printf( " pre-cached all sound data\n"); |
613 | 595 | ||
614 | // Now initialize mixbuffer with zero. |
596 | // Now initialize mixbuffer with zero. |
615 | // for ( i = 0; i< MIXBUFFERSIZE; i++ ) |
597 | // for ( i = 0; i< MIXBUFFERSIZE; i++ ) |
616 | // mixbuffer[i] = 0; |
598 | // mixbuffer[i] = 0; |
617 | 599 | ||
618 | // Finished initialization. |
600 | // Finished initialization. |
619 | printf("I_InitSound: sound module ready\n"); |
601 | printf("I_InitSound: sound module ready\n"); |
620 | 602 | ||
621 | } |
603 | } |
622 | 604 | ||
623 | 605 | ||
624 | // |
606 | // |
625 | // MUSIC API. |
607 | // MUSIC API. |
626 | // Still no music done. |
608 | // Still no music done. |
627 | // Remains. Dummies. |
609 | // Remains. Dummies. |
628 | // |
610 | // |
629 | void I_InitMusic(void) { } |
611 | void I_InitMusic(void) { } |
630 | void I_ShutdownMusic(void) { } |
612 | void I_ShutdownMusic(void) { } |
631 | 613 | ||
632 | static int looping=0; |
614 | static int looping=0; |
633 | static int musicdies=-1; |
615 | static int musicdies=-1; |
634 | 616 | ||
635 | void I_PlaySong(int handle, int looping) |
617 | void I_PlaySong(int handle, int looping) |
636 | { |
618 | { |
637 | // UNUSED. |
619 | // UNUSED. |
638 | handle = looping = 0; |
620 | handle = looping = 0; |
639 | musicdies = gametic + TICRATE*30; |
621 | musicdies = gametic + TICRATE*30; |
640 | } |
622 | } |
641 | 623 | ||
642 | void I_PauseSong (int handle) |
624 | void I_PauseSong (int handle) |
643 | { |
625 | { |
644 | // UNUSED. |
626 | // UNUSED. |
645 | handle = 0; |
627 | handle = 0; |
646 | } |
628 | } |
647 | 629 | ||
648 | void I_ResumeSong (int handle) |
630 | void I_ResumeSong (int handle) |
649 | { |
631 | { |
650 | // UNUSED. |
632 | // UNUSED. |
651 | handle = 0; |
633 | handle = 0; |
652 | } |
634 | } |
653 | 635 | ||
654 | void I_StopSong(int handle) |
636 | void I_StopSong(int handle) |
655 | { |
637 | { |
656 | // UNUSED. |
638 | // UNUSED. |
657 | handle = 0; |
639 | handle = 0; |
658 | 640 | ||
659 | looping = 0; |
641 | looping = 0; |
660 | musicdies = 0; |
642 | musicdies = 0; |
661 | } |
643 | } |
662 | 644 | ||
663 | void I_UnRegisterSong(int handle) |
645 | void I_UnRegisterSong(int handle) |
664 | { |
646 | { |
665 | // UNUSED. |
647 | // UNUSED. |
666 | handle = 0; |
648 | handle = 0; |
667 | } |
649 | } |
668 | 650 | ||
669 | int I_RegisterSong(void* data) |
651 | int I_RegisterSong(void* data) |
670 | { |
652 | { |
671 | // UNUSED. |
653 | // UNUSED. |
672 | data = NULL; |
654 | data = NULL; |
673 | 655 | ||
674 | return 1; |
656 | return 1; |
675 | } |
657 | } |
676 | 658 | ||
677 | // Is the song playing? |
659 | // Is the song playing? |
678 | int I_QrySongPlaying(int handle) |
660 | int I_QrySongPlaying(int handle) |
679 | { |
661 | { |
680 | // UNUSED. |
662 | // UNUSED. |
681 | handle = 0; |
663 | handle = 0; |
682 | return looping || musicdies > gametic; |
664 | return looping || musicdies > gametic; |
683 | } |
665 | } |
684 | 666 | ||
685 | 667 | ||
686 | // Interrupt handler. |
668 | // Interrupt handler. |
687 | void I_HandleSoundTimer( int ignore ) |
669 | void I_HandleSoundTimer( int ignore ) |
688 | { |
670 | { |
689 | 671 | ||
690 | // UNUSED, but required. |
672 | // UNUSED, but required. |
691 | ignore = 0; |
673 | ignore = 0; |
692 | return; |
674 | return; |
693 | }>>>>>>>256>128>128>>>> |
675 | }>>>>>>>256>128>128>>>> |