Subversion Repositories Kolibri OS

Rev

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

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