Subversion Repositories Kolibri OS

Rev

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