1 /*
2 swsound - SW sound generation
3
4 Copyright (C) 1984-2003 David L. Clark.
5 This program is free software; you can redistribute it and/or modify it under
6 the terms of the GNU General Public License as published by the Free Software
7 Foundation; either version 2 of the License, or (at your option) any later
8 version. This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 more details. You should have received a copy of the GNU General Public
12 License along with this program; if not, write to the Free Software Foundation,
13 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
14
15 Author: Dave Clark
16
17 Modification History:
18 84-04-11 Development
19 87-03-10 Microsoft compiler.
20 2003-01-27 GNU General Public License
21 */
22 #include "sw.h"
23
24
25
26 #define TIMER 0x40
27 #define PORTB 0x61
28 #define SNDSIZE 100
29
30
31 extern int soundflg; /* Sound flag */
32 extern int dispdbg; /* Debug value to be displayed */
33
34
35 static int soundtype = 32767; /* Current sound type and */
36 static int soundparm = 32767; /* and priority parameter */
37 static OBJECTS *soundobj = NULL; /* Object making sound */
38 static unsigned lastfreq = 0; /* Last frequency used */
39 static OBJECTS *lastobj = NULL; /* Previous object making sound */
40 static int ( *toneadj ) () = NULL; /* Tone adjustment on clock tick */
41
42 static TONETAB tonetab[SNDSIZE]; /* Continuous tone table */
43 static TONETAB *frsttone, *freetone; /* Tone list and free list */
44 static unsigned soundticks; /* Ticks since last sound selection*/
45
46 static int numexpls; /* Number of explosions currently */
47 /* active */
48 static int explplace; /* Place in explosion tune; */
49 static int explline; /* Line in explosion tune */
50 static unsigned expltone; /* Current explosion tone */
51 static int explticks; /* Ticks until note change */
52 static int exploctv; /* Octave */
53 static char *expltune[7] = {
54 "b4/d8/d2/r16/c8/b8/a8/b4./c4./c+4./d4./",
55 "e4/g8/g2/r16/>a8/a8/a2/r16/a2/r16/a8/c2/r16/",
59 "b8/a8/b4/b4/a4./tt_next = tt + 1;
89 tt->tt_next = NULL;
90 frsttone = NULL;
91 freetone = tonetab;
92 }
93
94
95
96 sound( type, parm, ob )
97 int type, parm;
98 OBJECTS *ob;
99 {
100
101 if ( type < soundtype ) {
102 soundtype = type;
103 soundparm = parm;
104 soundobj = ob;
105 } else
106 if ( ( type == soundtype ) && ( parm < soundparm ) ) {
107 soundparm = parm;
108 soundobj = ob;
109 }
110 }
111
112
113
114
115 swsound()
116 {
117 unsigned rand();
118 int adjcont(), adjshot();
119 register TONETAB *tt;
120
121 intsoff();
122 tt = frsttone;
123 while ( tt ) {
124 tt->tt_tone += ( tt->tt_chng * soundticks );
125 tt = tt->tt_next;
126 }
127
128 soundticks = 0;
129 titleflg = FALSE;
130
131 switch ( soundtype ) {
132
133 case 0:
134 case 32767:
135 default:
136 soundoff();
137 lastobj = NULL;
138 toneadj = NULL;
139 break;
140
141 case S_PLANE:
142 if ( soundparm == 0 )
143 tone( 0xF000 );
144 else
145 tone( 0xD000 + soundparm * 0x1000 );
146 lastobj = NULL;
147 toneadj = NULL;
148 break;
149
150 case S_BOMB:
151 if ( soundobj == lastobj )
152 break;
153 toneadj = adjcont;
154 lastobj = soundobj;
155 adjcont();
156 break;
157
158 case S_FALLING:
159 if ( soundobj == lastobj )
160 break;
161 toneadj = adjcont;
162 lastobj = soundobj;
163 adjcont();
164 break;
165
166 case S_HIT:
167 tone( rand( 2 ) ? 0x9000 : 0xF000 );
168 lastobj = NULL;
169 toneadj = NULL;
170 break;
171
172 case S_EXPLOSION:
173 tone( expltone );
174 toneadj = NULL;
175 lastobj = NULL;
176 break;
177
178 case S_SHOT:
179 tone( 0x1000 );
180 toneadj = adjshot;
181 lastobj = NULL;
182 break;
183
184 case S_TITLE:
185 titlline = 0;
186 titlplace = 0;
187 titlnote();
188 toneadj = NULL;
189 lastobj = NULL;
190 titleflg = TRUE;
191 break;
192
193 }
194
195 intson();
196 soundtype = soundparm = 32767;
197 }
198
199
200
201
202
203 soundadj()
204 {
205
206 ++soundticks;
207
208 if ( lastfreq && toneadj )
209 ( *toneadj )();
210
211 if ( numexpls )
212 adjexpl();
213
214 if ( titleflg )
215 adjtitl();
216 }
217
218
219
220
221 static adjcont()
222 {
223 register TONETAB *tt;
224
225 if ( tt = lastobj->ob_sound )
226 tone( tt->tt_tone + tt->tt_chng * soundticks );
227 }
228
229
230
231
232 static adjshot()
233 {
234 static unsigned savefreq;
235
236 if ( lastfreq == 0xF000 )
237 tone( savefreq );
238 else {
239 savefreq = lastfreq;
240 tone( 0xF000 );
241 }
242 }
243
244
245
246
247 static adjexpl()
248 {
249 if ( --explticks >= 0 )
250 return;
251
252 explnote();
253 }
254
255
256
257
258 static explnote()
259 {
260 line = explline;
261 place = explplace;
262 tune = expltune;
263 octavefactor = exploctv;
264 playnote();
265 explline = line;
266 explplace = place;
267 expltone = tunefreq;
268 intsoff();
269 explticks += tunedura;
270 intson();
271 exploctv = octavefactor;
272 }
273
274
275
276
277 static adjtitl()
278 {
279 if ( --titlticks >= 0 )
280 return;
281 titlnote();
282 }
283
284
285
286
287 static titlnote()
288 {
289
290 line = titlline;
291 place = titlplace;
292 tune = expltune;
293 octavefactor = titloctv;
294 playnote();
295 titlline = line;
296 titlplace = place;
297 titltone = tunefreq;
298 intsoff();
299 titlticks += tunedura;
300 intson();
301 titloctv = octavefactor;
302 soundoff();
303 tone( titltone );
304 }
305
306
307
308
309
310 initsound( obp, type )
311 OBJECTS *obp;
312 int type;
313 {
314 register OBJECTS *ob;
315 register TONETAB *tt;
316 TONETAB *allocton();
317
318 if ( ( ob = obp )->ob_sound )
319 return;
320
321 if ( ob->ob_type == EXPLOSION ) {
322 intsoff();
323 if ( ++numexpls == 1 ) {
324 explline = 0;
325 explplace = 0;
326 explnote();
327 }
328 ob->ob_sound = (struct tt *) 1;
329 intson();
330 return;
331 }
332
333 if ( tt = allocton() ) {
334 intsoff();
335 switch ( type ) {
336 case S_BOMB:
337 tt->tt_tone = 0x0300;
338 tt->tt_chng = 8;
339 break;
340 case S_FALLING:
341 tt->tt_tone = 0x1200;
342 tt->tt_chng = -8;
343 break;
344 default:
345 break;
346 }
347 ob->ob_sound = tt;
348 intson();
349 return;
350 }
351 }
352
353
354
355
356 static TONETAB *allocton()
357 {
358 register TONETAB *tt;
359
360 if ( !freetone )
361 return( 0 );
362
363 tt = freetone;
364 freetone = tt->tt_next;
365
366 tt->tt_next = frsttone;
367 tt->tt_prev = NULL;
368
369 if ( frsttone )
370 frsttone->tt_prev = tt;
371
372 return( frsttone = tt );
373 }
374
375
376
377 static deallton( ttp )
378 TONETAB *ttp;
379 {
380 register TONETAB *ttb, *tt;
381
382
383 if ( ttb = ( tt = ttp )->tt_prev )
384 ttb->tt_next = tt->tt_next;
385 else
386 frsttone = tt->tt_next;
387
388 if ( ttb = tt->tt_next )
389 ttb->tt_prev = tt->tt_prev;
390
391 tt->tt_next = freetone;
392 freetone = tt;
393 }
394
395
396
397
398
399
400
401
402 stopsound( ob )
403 OBJECTS *ob;
404 {
405 TONETAB *tt;
406
407 if ( !( tt = ob->ob_sound ) )
408 return;
409
410 intsoff();
411 if ( ob->ob_type == EXPLOSION )
412 --numexpls;
413 else
414 deallton( tt );
415 ob->ob_sound = NULL;
416 intson();
417 }
418
419
420
421
422
423
424 static tone( freq )
425 unsigned freq;
426 {
427
428 if ( !soundflg )
429 return;
430
431 if ( lastfreq == freq )
432 return;
433
434 #ifdef IBMPC
435 if ( !lastfreq )
436 outportb( TIMER + 3, 0xB6 );
437 outportb( TIMER + 2, freq & 0x00FF );
438 outportb( TIMER + 2, freq >> 8 );
439 if ( !lastfreq )
440 outportb( PORTB, 0x03 | inportb( PORTB ) );
441 #endif
442
443 lastfreq = freq;
444 dispdbg = freq;
445 }
446
447
448
449
450 soundoff()
451 {
452 if ( lastfreq ) {
453 #ifdef IBMPC
454 outportb( PORTB, 0xFC & inportb( PORTB ) );
455 #endif
456 lastfreq = 0;
457 dispdbg = 0;
458 }
459 }
460
461
462
463
464
465 static int seed[50] = {
466 0x90B9, 0xBCFB, 0x6564, 0x3313, 0x3190, 0xA980, 0xBCF0, 0x6F97,
467 0x37F4, 0x064B, 0x9FD8, 0x595B, 0x1EEE, 0x820C, 0x4201, 0x651E,
468 0x848E, 0x15D5, 0x1DE7, 0x1585, 0xA850, 0x213B, 0x3953, 0x1EB0,
469 0x97A7, 0x35DD, 0xAF2F, 0x1629, 0xBE9B, 0x243F, 0x847D, 0x313A,
470 0x3295, 0xBC11, 0x6E6D, 0x3398, 0xAD43, 0x51CE, 0x8F95, 0x507E,
471 0x499E, 0x3BC1, 0x5243, 0x2017, 0x9510, 0x9865, 0x65F6, 0x6B56,
472 0x36B9, 0x5026
473 };
474
475
476
477 static unsigned rand( modulo )
478 unsigned modulo;
479 {
480 static i = 0;
481
482 if ( i >= 50 )
483 i = 0;
484 return( seed[i++] % modulo );
485 }
486
487
488
489
490
491
492
493 #define NOTEEND '/'
494 #define UPOCTAVE '>'
495 #define DOWNOCTAVE '<'
496 #define SHARP '+'
497 #define FLAT '-'
498 #define DOT '.'
499 #define REST 'R'
500
501
502
503
504
505 playnote()
506 {
507
508 static int noteindex[] = { 0,2,3,5,7,8,10 };
509 static int notefreq[] = {440,466,494,523,554,587,622,659,698,740,784,831};
510
511 static int durplace, test, freq, duration;
512 static int index;
513 static int indexadj;
514
515 static char durstring[5];
516 static char charatplace, noteletter;
517
518 static int noteoctavefactor;
519 static int dottednote;
520
521 BOOL firstplace = TRUE;
522
523 indexadj = 0;
524 durplace = 0;
525 dottednote = 2;
526 noteoctavefactor = 256;
527
528 FOREVER {
529 if ( ( !line ) && ( !place ) )
530 octavefactor = 256;
531
532 if ( !( charatplace = toupper( tune[line][place++] ) ) ) {
533 if ( !( charatplace = tune[++line][place = 0] ) ) {
534 line = 0;
535 }
536
537 if ( firstplace )
538 continue;
539 break;
540 }
541 firstplace = FALSE;
542 if ( charatplace == NOTEEND )
543 break;
544
545 if ( test = isalpha( charatplace )) {
546 index = *(noteindex + (charatplace - 'A'));
547 noteletter = charatplace;
548 } else
549 switch( charatplace ) {
550 case UPOCTAVE : octavefactor <<= 1; break;
551 case DOWNOCTAVE : octavefactor >>= 1; break;
552 case SHARP : indexadj++; break;
553 case FLAT : indexadj--; break;
554 case DOT : dottednote = 3; break;
555 default :
556 if ( test = isdigit(charatplace))
557 *(durstring + durplace++) = charatplace;
558 break;
559 }
560
561 }
562
563 *(durstring + durplace) = '\0';
564 duration = atoi( durstring );
565 if (duration <= 0) duration = 4;
566 duration = (1440 * dottednote / (60*duration)) >> 1;
567
568 if (noteletter == REST)
569 freq = 32000;
570 else {
571 index += indexadj;
572 while (index < 0) {
573 index += 12;
574 noteoctavefactor >>= 1 ;
575 }
576 while ( index >= 12 ) {
577 index -= 12;
578 noteoctavefactor <<= 1 ;
579 }
580 freq = soundmul( *(notefreq+index), octavefactor, noteoctavefactor );
581 }
582 tunefreq = sounddiv( 1331000L, freq );
583 tunedura = duration;
584 }
585 ÿ