Subversion Repositories Kolibri OS

Rev

Rev 298 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
298 serge 1
// Emacs style mode select   -*- C++ -*-
2
//-----------------------------------------------------------------------------
3
//
4
// $Id:$
5
//
6
// Copyright (C) 1993-1996 by id Software, Inc.
7
//
8
// This source is available for distribution and/or modification
9
// only under the terms of the DOOM Source Code License as
10
// published by id Software. All rights reserved.
11
//
12
// The source is distributed in the hope that it will be useful,
13
// but WITHOUT ANY WARRANTY; without even the implied warranty of
14
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
15
// for more details.
16
//
17
// $Log:$
18
//
19
// DESCRIPTION:  none
20
//
21
//-----------------------------------------------------------------------------
22
 
23
 
24
static const char
25
rcsid[] = "$Id: s_sound.c,v 1.6 1997/02/03 22:45:12 b1 Exp $";
26
 
27
 
28
#include 
29
#include 
30
 
31
#include "i_system.h"
32
#include "i_sound.h"
33
#include "sounds.h"
34
#include "s_sound.h"
35
 
36
#include "z_zone.h"
37
#include "m_random.h"
38
#include "w_wad.h"
39
 
40
#include "doomdef.h"
41
#include "p_local.h"
42
//#include "m_music.h"
43
 
44
#include "doomstat.h"
45
 
46
//#include "qmus2mid.h"
47
 
48
void WriteDebug(char *);
49
 
50
// Purpose?
51
const char snd_prefixen[]
52
= { 'P', 'P', 'A', 'S', 'S', 'S', 'M', 'M', 'M', 'S', 'S', 'S' };
53
 
333 serge 54
#define S_MAX_VOLUME            127
298 serge 55
 
56
// when to clip out sounds
57
// Does not fit the large outdoor areas.
333 serge 58
#define S_CLIPPING_DIST         (1200*0x10000)
298 serge 59
 
60
// Distance tp origin when sounds should be maxed out.
61
// This should relate to movement clipping resolution
62
// (see BLOCKMAP handling).
63
// Originally: (200*0x10000).
333 serge 64
#define S_CLOSE_DIST            (160*0x10000)
298 serge 65
 
66
 
333 serge 67
#define S_ATTENUATOR            ((S_CLIPPING_DIST-S_CLOSE_DIST)>>FRACBITS)
298 serge 68
 
69
// Adjustable by menu.
333 serge 70
#define NORM_VOLUME             snd_MaxVolume
298 serge 71
 
333 serge 72
#define NORM_PITCH              128
73
#define NORM_PRIORITY           64
74
#define NORM_SEP                128
298 serge 75
 
333 serge 76
#define S_PITCH_PERTURB         1
77
#define S_STEREO_SWING          (96*0x10000)
298 serge 78
 
79
// percent attenuation from front to back
333 serge 80
#define S_IFRACVOL              30
298 serge 81
 
333 serge 82
#define NA                      0
83
//#define S_NUMCHANNELS         2
84
#define NUM_CHANNELS    16
298 serge 85
 
86
// Current music/sfx card - index useless
87
//  w/o a reference LUT in a sound module.
88
extern int snd_MusicDevice;
89
extern int snd_SfxDevice;
90
// Config file? Same disclaimer as above.
91
extern int snd_DesiredMusicDevice;
92
extern int snd_DesiredSfxDevice;
93
 
94
 
95
typedef struct
96
{
97
    // sound information (if null, channel avail.)
333 serge 98
    sfxinfo_t*  sfxinfo;
298 serge 99
 
100
    // origin of sound
333 serge 101
    void*       origin;
298 serge 102
 
103
    // handle of the sound being played
333 serge 104
    int         handle;
298 serge 105
 
106
} channel_t;
107
 
108
 
109
// the set of channels available
333 serge 110
static channel_t*       channels;
298 serge 111
 
112
// These are not used, but should be (menu).
113
// Maximum volume of a sound effect.
114
// Internal default is max out of 0-15.
333 serge 115
int             snd_SfxVolume = 80;
298 serge 116
 
117
// Maximum volume of music. Useless so far.
333 serge 118
int             snd_MusicVolume = 80;
298 serge 119
 
120
 
121
 
122
// whether songs are mus_paused
333 serge 123
static boolean          mus_paused;
298 serge 124
 
125
// music currently being played
333 serge 126
static musicinfo_t*     mus_playing=0;
298 serge 127
 
128
// following is set
129
//  by the defaults code in M_misc:
130
// number of channels available
333 serge 131
int                     numChannels;
298 serge 132
 
333 serge 133
static int              nextcleanup;
298 serge 134
 
135
 
136
 
137
//
138
// Internals.
139
//
140
int
141
S_getChannel
333 serge 142
( void*         origin,
143
  sfxinfo_t*    sfxinfo,
298 serge 144
  int       sfxid );
145
 
146
 
147
int
148
S_AdjustSoundParams
333 serge 149
( mobj_t*       listener,
150
  mobj_t*       source,
151
  int*          vol,
152
  int*          sep,
153
  int*          pitch );
298 serge 154
 
155
void S_StopChannel(int cnum);
156
 
157
 
158
 
159
//
160
// Initializes sound stuff, including volume
161
// Sets channels, SFX and music volume,
162
//  allocates channel buffer, sets S_sfx lookup.
163
//
164
void S_Init
333 serge 165
( int           sfxVolume,
166
  int           musicVolume )
298 serge 167
{
333 serge 168
  int           i;
298 serge 169
 
170
  printf("S_Init: default sfx volume %d\n", sfxVolume);
171
 
333 serge 172
  //I_CreateSound();
298 serge 173
  numChannels = NUM_CHANNELS;
174
 
175
  // Whatever these did with DMX, these are rather dummies now.
176
  I_SetChannels();
177
 
178
  S_SetSfxVolume(sfxVolume);
179
  // No music with Linux - another dummy.
180
  S_SetMusicVolume(musicVolume);
181
 
182
  // Allocating the internal channels for mixing
183
  // (the maximum numer of sounds rendered
184
  // simultaneously) within zone memory.
185
  channels =
186
    (channel_t *) Z_Malloc(numChannels*sizeof(channel_t), PU_STATIC, 0);
187
 
188
  // Free all channels for use
189
  for (i=0 ; i
190
    channels[i].sfxinfo = 0;
191
 
192
  // no sounds are playing, and they are not mus_paused
193
  mus_paused = 0;
194
 
195
  // Note that sounds have not been cached (yet).
196
  for (i=1 ; i
197
    S_sfx[i].lumpnum = S_sfx[i].usefulness = -1;
198
}
199
 
200
//
201
// Per level startup code.
202
// Kills playing sounds at start of level,
203
//  determines music if any, changes music.
204
//
205
void S_Start(void)
206
{
207
  int cnum;
208
  int mnum;
209
 
210
  // kill all playing sounds at start of level
211
  //  (trust me - a good idea)
212
  for (cnum=0 ; cnum
213
    if (channels[cnum].sfxinfo)
214
      S_StopChannel(cnum);
215
 
216
  // start new music for the level
217
  mus_paused = 0;
218
 
219
  if (gamemode == commercial)
333 serge 220
          mnum = mus_runnin + gamemap - 1;
298 serge 221
  else
222
  {
333 serge 223
          int spmus[]=
224
          {
225
                  // Song - Who? - Where?
226
                mus_e3m4,       // American     e4m1
227
                mus_e3m2,       // Romero       e4m2
228
                mus_e3m3,       // Shawn        e4m3
229
                mus_e1m5,       // American     e4m4
230
                mus_e2m7,       // Tim  e4m5
231
                mus_e2m4,       // Romero       e4m6
232
                mus_e2m6,       // J.Anderson   e4m7 CHIRON.WAD
233
                mus_e2m5,       // Shawn        e4m8
234
                mus_e1m9        // Tim          e4m9
235
          };
236
 
237
          if (gameepisode < 4)
238
                  mnum = mus_e1m1 + (gameepisode-1)*9 + gamemap-1;
239
          else
240
                  mnum = spmus[gamemap-1];
241
  }
298 serge 242
 
243
  // HACK FOR COMMERCIAL
333 serge 244
  //  if (commercial && mnum > mus_e3m9)
298 serge 245
  //      mnum -= mus_e3m9;
246
 
247
  S_ChangeMusic(mnum, true);
248
 
249
  nextcleanup = 15;
333 serge 250
}
298 serge 251
 
252
void S_StartSoundAtVolume( void *origin_p, int sfx_id, int volume )
253
   {
254
    int        rc;
255
    int        sep;
256
    int        pitch;
257
    int        priority;
258
    sfxinfo_t *sfx;
259
    int        cnum;
260
    // int        chnum;  <-- 10.9.98 compiler warning
261
 
333 serge 262
    mobj_t*     origin = (mobj_t *)origin_p;
298 serge 263
 
264
    //WriteDebug("S_StartSoundAtVolume...\n");
265
 
266
    // Debug.
267
    /*fprintf( stderr,"S_StartSoundAtVolume: playing sound %d (%s)\n",sfx_id, S_sfx[sfx_id].name );*/
268
 
269
    // check for bogus sound #
270
    if (sfx_id < 1 || sfx_id > NUMSFX)
271
        I_Error("Bad sfx #: %d", sfx_id);
272
 
273
    sfx = &S_sfx[sfx_id];
274
 
275
    // Initialize sound parameters
276
    if (sfx->link)
277
       {
278
        pitch = sfx->pitch;
279
        priority = sfx->priority;
280
        volume += sfx->volume;
281
 
282
        if (volume < 1)
283
           {
284
            //WriteDebug("Volume off...\n");
285
            return;
286
           }
287
 
288
        if (volume > snd_SfxVolume)
289
            volume = snd_SfxVolume;
333 serge 290
       }
298 serge 291
    else
292
       {
293
        pitch = NORM_PITCH;
294
        priority = NORM_PRIORITY;
295
       }
296
 
297
 
298
    // Check to see if it is audible,
299
    //  and if not, modify the params
300
    if (origin && origin != players[consoleplayer].mo)
301
       {
302
        rc = S_AdjustSoundParams(players[consoleplayer].mo, origin, &volume, &sep, &pitch);
303
        if ( origin->x == players[consoleplayer].mo->x && origin->y == players[consoleplayer].mo->y)
333 serge 304
           {
298 serge 305
            sep = NORM_SEP;
306
           }
307
        if (!rc)
308
           {
309
            //WriteDebug("No rc from S_AdjustSoundParams...\n");
310
            return;
311
           }
333 serge 312
       }
298 serge 313
    else
314
       {
315
        sep = NORM_SEP;
316
       }
317
 
318
    // hacks to vary the sfx pitches
319
    if (sfx_id >= sfx_sawup && sfx_id <= sfx_sawhit)
333 serge 320
       {
298 serge 321
        pitch += 8 - (M_Random()&15);
322
        if (pitch < 0)
323
            pitch = 0;
324
        else
325
        if (pitch>255)
326
            pitch = 255;
327
       }
328
    else
329
    if (sfx_id != sfx_itemup && sfx_id != sfx_tink)
330
       {
331
        pitch += 16 - (M_Random()&31);
332
        if (pitch<0)
333
            pitch = 0;
334
        else
335
        if (pitch > 255)
336
            pitch = 255;
337
       }
338
 
339
  // kill old sound
340
  S_StopSound(origin);
341
 
342
  // try to find a channel
343
  cnum = S_getChannel(origin, sfx, sfx_id);
344
 
345
  if (cnum<0)
346
     {
347
        //WriteDebug("cnum < 0 -- no channel...\n");
348
    return;
349
     }
350
 
351
  //
352
  // This is supposed to handle the loading/caching.
353
  // For some odd reason, the caching is done nearly
354
  //  each time the sound is needed?
355
  //
356
 
357
  // get lumpnum if necessary
358
  if (sfx->lumpnum < 0)
359
    sfx->lumpnum = I_GetSfxLumpNum(sfx);
360
 
361
  // cache data if necessary
362
  if (!sfx->data)
363
  {
364
    sfx->data = (void *) W_CacheLumpNum(sfx->lumpnum, PU_MUSIC);
365
 
366
  }
367
 
368
  // increase the usefulness
369
  if (sfx->usefulness++ < 0)
370
      sfx->usefulness = 1;
371
 
372
  // Assigns the handle to one of the channels in the
373
  //  mix/output buffer.
374
  //WriteDebug("I_StartSound...\n");
333 serge 375
  channels[cnum].handle = I_StartSound(sfx_id,volume,sep,pitch,priority);
298 serge 376
  channels[cnum].handle = cnum;
377
  channels[cnum].sfxinfo = sfx;
378
  channels[cnum].origin = origin;
333 serge 379
}
298 serge 380
 
381
void S_StartSound( void *origin, int sfx_id )
382
   {
383
#ifdef SAWDEBUG
384
    // if (sfx_id == sfx_sawful)
385
    // sfx_id = sfx_itemup;
386
#endif
387
 
388
    S_StartSoundAtVolume(origin, sfx_id, snd_SfxVolume);
389
 
390
 
391
    // UNUSED. We had problems, had we not?
392
#ifdef SAWDEBUG
393
{
394
    int i;
395
    int n;
333 serge 396
 
298 serge 397
    static mobj_t*      last_saw_origins[10] = {1,1,1,1,1,1,1,1,1,1};
333 serge 398
    static int          first_saw=0;
399
    static int          next_saw=0;
400
 
298 serge 401
    if (sfx_id == sfx_sawidl
333 serge 402
        || sfx_id == sfx_sawful
403
        || sfx_id == sfx_sawhit)
298 serge 404
    {
333 serge 405
        for (i=first_saw;i!=next_saw;i=(i+1)%10)
406
            if (last_saw_origins[i] != origin)
407
                fprintf(stderr, "old origin 0x%lx != "
408
                        "origin 0x%lx for sfx %d\n",
409
                        last_saw_origins[i],
410
                        origin,
411
                        sfx_id);
412
 
413
        last_saw_origins[next_saw] = origin;
414
        next_saw = (next_saw + 1) % 10;
415
        if (next_saw == first_saw)
416
            first_saw = (first_saw + 1) % 10;
417
 
418
        for (n=i=0; i
419
        {
420
            if (channels[i].sfxinfo == &S_sfx[sfx_sawidl]
421
                || channels[i].sfxinfo == &S_sfx[sfx_sawful]
422
                || channels[i].sfxinfo == &S_sfx[sfx_sawhit]) n++;
423
        }
424
 
425
        if (n>1)
426
        {
427
            for (i=0; i
428
            {
429
                if (channels[i].sfxinfo == &S_sfx[sfx_sawidl]
430
                    || channels[i].sfxinfo == &S_sfx[sfx_sawful]
431
                    || channels[i].sfxinfo == &S_sfx[sfx_sawhit])
432
                {
433
                    fprintf(stderr,
434
                            "chn: sfxinfo=0x%lx, origin=0x%lx, "
435
                            "handle=%d\n",
436
                            channels[i].sfxinfo,
437
                            channels[i].origin,
438
                            channels[i].handle);
439
                }
440
            }
441
            fprintf(stderr, "\n");
442
        }
298 serge 443
    }
444
}
445
#endif
446
 
447
}
448
 
449
 
450
 
451
 
452
void S_StopSound(void *origin)
453
{
454
 
455
    int cnum;
456
 
457
    for (cnum=0 ; cnum
458
    {
333 serge 459
        if (channels[cnum].sfxinfo && channels[cnum].origin == origin)
460
        {
461
            S_StopChannel(cnum);
462
            break;
463
        }
298 serge 464
    }
465
}
466
 
467
 
468
 
469
 
470
 
471
 
472
 
473
 
474
 
475
//
476
// Stop and resume music, during game PAUSE.
477
//
478
void S_PauseSound(void)
479
{
480
    if (mus_playing && !mus_paused)
481
    {
333 serge 482
        I_PauseSong(mus_playing->handle);
483
        mus_paused = true;
298 serge 484
    }
485
}
486
 
487
void S_ResumeSound(void)
488
{
489
    if (mus_playing && mus_paused)
490
    {
333 serge 491
        I_ResumeSong(mus_playing->handle);
492
        mus_paused = false;
298 serge 493
    }
494
}
495
 
496
 
497
//
498
// Updates music & sounds
499
//
500
void S_UpdateSounds(void* listener_p)
501
{
333 serge 502
    int         audible;
503
    int         cnum;
504
    int         volume;
505
    int         sep;
506
    int         pitch;
507
    sfxinfo_t*  sfx;
508
    channel_t*  c;
298 serge 509
 
333 serge 510
    mobj_t*     listener = (mobj_t*)listener_p;
298 serge 511
 
512
 
513
 
514
    // Clean up unused data.
515
    // This is currently not done for 16bit (sounds cached static).
516
    // DOS 8bit remains.
517
    /*if (gametic > nextcleanup)
518
    {
333 serge 519
        for (i=1 ; i
520
        {
521
            if (S_sfx[i].usefulness < 1
522
                && S_sfx[i].usefulness > -1)
523
            {
524
                if (--S_sfx[i].usefulness == -1)
525
                {
526
                    Z_ChangeTag(S_sfx[i].data, PU_CACHE);
527
                    S_sfx[i].data = 0;
528
                }
529
            }
530
        }
531
        nextcleanup = gametic + 15;
298 serge 532
    }*/
533
 
534
    for (cnum=0 ; cnum
535
    {
333 serge 536
        c = &channels[cnum];
537
        sfx = c->sfxinfo;
298 serge 538
 
333 serge 539
        if (c->sfxinfo)
540
        {
541
            if (I_SoundIsPlaying(c->handle))
542
            {
543
                // initialize parameters
544
                volume = snd_SfxVolume;
545
                pitch = NORM_PITCH;
546
                sep = NORM_SEP;
298 serge 547
 
333 serge 548
                if (sfx->link)
549
                {
550
                    pitch = sfx->pitch;
551
                    volume += sfx->volume;
552
                    if (volume < 1)
553
                    {
554
                        S_StopChannel(cnum);
555
                        continue;
556
                    }
557
                    else if (volume > snd_SfxVolume)
558
                    {
559
                        volume = snd_SfxVolume;
560
                    }
561
                }
298 serge 562
 
333 serge 563
                // check non-local sounds for distance clipping
564
                //  or modify their params
565
                if (c->origin && listener_p != c->origin)
566
                {
567
                    audible = S_AdjustSoundParams(listener,
568
                                                  c->origin,
569
                                                  &volume,
570
                                                  &sep,
571
                                                  &pitch);
572
 
573
                    if (!audible)
574
                    {
575
                        S_StopChannel(cnum);
576
                    }
577
                    else
578
                        I_UpdateSoundParams(c->handle, volume, sep, pitch);
579
                }
580
            }
581
            else
582
            {
583
                // if channel is allocated but sound has stopped,
584
                //  free it
585
                S_StopChannel(cnum);
586
            }
587
        }
298 serge 588
    }
589
    // kill music if it is a single-play && finished
333 serge 590
    // if (     mus_playing
298 serge 591
    //      && !I_QrySongPlaying(mus_playing->handle)
592
    //      && !mus_paused )
593
    // S_StopMusic();
594
}
595
 
596
 
597
void S_SetMusicVolume(int volume)
598
{
599
    if (volume < 0 || volume > 127)
600
    {
333 serge 601
        I_Error("Attempt to set music volume at %d",
602
                volume);
298 serge 603
    }
604
 
605
    I_SetMusicVolume(127);
606
    I_SetMusicVolume(volume);
607
    snd_MusicVolume = volume;
608
}
609
 
610
 
611
 
612
void S_SetSfxVolume(int volume)
613
{
614
 
615
    if (volume < 0 || volume > 127)
333 serge 616
        I_Error("Attempt to set sfx volume at %d", volume);
298 serge 617
 
618
    snd_SfxVolume = volume;
619
 
620
}
621
 
622
//
623
// Starts some music with the music id found in sounds.h.
624
//
625
void S_StartMusic(int m_id)
626
{
627
//    S_ChangeMusic(m_id, false);
628
}
629
 
630
 
631
// clean-up&code for orig midi 10.9.98-dlw
632
void S_ChangeMusic(int musicnum, int looping)
633
{
634
 
635
    // I_PlaySong(music->handle, looping);
333 serge 636
//      mus_playing = music;
298 serge 637
}
638
 
639
 
640
void S_StopMusic(void)
641
{
642
    if (mus_playing)
643
    {
333 serge 644
                if (mus_paused) I_ResumeSong(mus_playing->handle);
645
                I_StopSong(mus_playing->handle);
646
                I_UnRegisterSong(mus_playing->handle);
647
                Z_ChangeTag(mus_playing->data, PU_CACHE);
648
                mus_playing->data = 0;
649
                mus_playing = 0;
298 serge 650
    }
651
}
652
 
653
void S_StopChannel(int cnum)
654
{
655
 
333 serge 656
    int         i;
657
    channel_t*  c = &channels[cnum];
298 serge 658
 
659
    if (c->sfxinfo)
660
    {
333 serge 661
        // stop the sound playing
662
        if (I_SoundIsPlaying(c->handle))
663
        {
298 serge 664
#ifdef SAWDEBUG
333 serge 665
            if (c->sfxinfo == &S_sfx[sfx_sawful])
666
                fprintf(stderr, "stopped\n");
298 serge 667
#endif
333 serge 668
            I_StopSound(c->handle);
669
        }
298 serge 670
 
333 serge 671
        // check to see
672
        //  if other channels are playing the sound
673
        for (i=0 ; i
674
        {
675
            if (cnum != i
676
                && c->sfxinfo == channels[i].sfxinfo)
677
            {
678
                break;
679
            }
680
        }
681
 
682
        // degrade usefulness of sound data
683
        c->sfxinfo->usefulness--;
298 serge 684
 
333 serge 685
        c->sfxinfo = 0;
298 serge 686
    }
687
}
688
 
689
 
690
//
691
// Changes volume, stereo-separation, and pitch variables
692
//  from the norm of a sound effect to be played.
693
// If the sound is not audible, returns a 0.
694
// Otherwise, modifies parameters and returns 1.
695
//
696
int
697
S_AdjustSoundParams (mobj_t* listener, mobj_t* source,
698
                     int* vol, int* sep, int* pitch)
699
{
333 serge 700
    fixed_t     approx_dist;
701
    fixed_t     adx;
702
    fixed_t     ady;
703
    angle_t     angle;
298 serge 704
 
705
    // calculate the distance to sound origin
706
    //  and clip it if necessary
707
    adx = abs(listener->x - source->x);
708
    ady = abs(listener->y - source->y);
709
 
710
    // From _GG1_ p.428. Appox. eucledian distance fast.
711
    approx_dist = adx + ady - ((adx < ady ? adx : ady)>>1);
712
 
713
    if (gamemap != 8
333 serge 714
        && approx_dist > S_CLIPPING_DIST)
298 serge 715
    {
333 serge 716
        return 0;
298 serge 717
    }
718
 
719
    // angle of source to listener
720
    angle = R_PointToAngle2(listener->x,
333 serge 721
                            listener->y,
722
                            source->x,
723
                            source->y);
298 serge 724
 
725
    if (angle > listener->angle)
333 serge 726
        angle = angle - listener->angle;
298 serge 727
    else
333 serge 728
        angle = angle + (0xffffffff - listener->angle);
298 serge 729
 
730
    angle >>= ANGLETOFINESHIFT;
731
 
732
    // stereo separation
733
    *sep = 128 - (FixedMul(S_STEREO_SWING,finesine[angle])>>FRACBITS);
734
 
735
    // volume calculation
736
    if (approx_dist < S_CLOSE_DIST)
737
    {
333 serge 738
        *vol = snd_SfxVolume;
298 serge 739
    }
740
    else if (gamemap == 8)
741
    {
333 serge 742
        if (approx_dist > S_CLIPPING_DIST)
743
            approx_dist = S_CLIPPING_DIST;
298 serge 744
 
333 serge 745
        *vol = 15+ ((snd_SfxVolume-15)
746
                    *((S_CLIPPING_DIST - approx_dist)>>FRACBITS))
747
            / S_ATTENUATOR;
298 serge 748
    }
749
    else
750
    {
333 serge 751
        // distance effect
752
        *vol = (snd_SfxVolume
753
                * ((S_CLIPPING_DIST - approx_dist)>>FRACBITS))
754
            / S_ATTENUATOR;
298 serge 755
    }
756
 
757
    return (*vol > 0);
758
}
759
 
760
//
761
// S_getChannel :
762
//   If none available, return -1.  Otherwise channel #.
763
//
764
int S_getChannel( void *origin, sfxinfo_t *sfxinfo, int sfxid )
765
   {
766
    // channel number to use
333 serge 767
    int         cnum;
298 serge 768
 
333 serge 769
    channel_t*  c;
298 serge 770
 
771
    // Find an open channel
772
    //for (cnum = 0; cnum < numChannels; cnum++)
773
    for (cnum = 0; cnum < NUM_CHANNELS; cnum++)
774
       {
775
        if (!channels[cnum].sfxinfo)
776
            break;
777
        else
778
        if (origin && channels[cnum].origin == origin)
779
           {
780
            S_StopChannel(cnum);
781
            break;
782
           }
783
       }
784
 
785
    // None available
786
    if (cnum == NUM_CHANNELS)
787
       {
788
        // Look for lower priority
789
        for (cnum = NUMSFX; cnum < NUM_CHANNELS; cnum++)
790
             if (channels[cnum].sfxinfo->priority >= sfxinfo->priority)
791
                 break;
792
 
793
        if (cnum == numChannels)
794
           {
795
            // FUCK!  No lower priority.  Sorry, Charlie.
796
            return -1;
797
           }
798
        else
799
           {
800
            // Otherwise, kick out lower priority.
801
            S_StopChannel(cnum);
802
           }
803
       }
804
 
805
    c = &channels[cnum];
806
 
807
    // channel is decided to be cnum.
808
    c->sfxinfo = sfxinfo;
809
    c->origin = origin;
810
 
811
    return cnum;
812
   }
813
 
814
 
815