Subversion Repositories Kolibri OS

Rev

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