]> icculus.org git repositories - btb/d2x.git/blob - main/old/windigi.c
Rename include/error.h to include/dxxerror.h
[btb/d2x.git] / main / old / windigi.c
1 /*
2 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
3 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
4 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
5 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
6 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
7 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
8 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
9 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
10 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.  
11 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
12 */
13
14
15 #include "desw.h"
16 #include "win\ds.h"
17 #include <mmsystem.h>
18 #include <mmreg.h>
19
20 #include<stdlib.h>
21 #include<stdio.h>
22 #include<dos.h>
23 #include<fcntl.h> 
24 #include<malloc.h> 
25 #include<bios.h>
26 #include<io.h>
27 #include<string.h>
28 #include<ctype.h>
29
30 #include "fix.h"
31 #include "object.h"
32 #include "mono.h"
33 #include "timer.h"
34 #include "joy.h"
35 #include "digi.h"
36 #include "sounds.h"
37 #include "args.h"
38 #include "key.h"
39 #include "newdemo.h"
40 #include "game.h"
41 #include "dxxerror.h"
42 #include "wall.h"
43 #include "cfile.h"
44 #include "piggy.h"
45 #include "text.h"
46
47 #pragma pack (4);                                               // Use 32-bit packing!
48 #pragma off (check_stack);                      // No stack checking!
49
50 #include "win\winmidi.h"
51 #include "config.h"
52
53 #define MAX_CHANNELS 32
54
55 typedef struct digi_channel {
56         ubyte           used;                           // Non-zero if a sound is playing on this channel 
57         int             soundnum;               // Which sound effect is on this channel, -1 if none
58         WORD            handle;                 // What SS handle this is playing on
59         int             soundobj;               // Which soundobject is on this channel
60         int             persistant;             // This can't be pre-empted
61         int             volume;                 // the volume of this channel
62 } digi_channel;
63
64
65 //      Defines
66 //      ----------------------------------------------------------------------------
67
68 #define DIGI_PAUSE_BROKEN 1             //if this is defined, don't pause MIDI songs
69 #define _DIGI_SAMPLE_FLAGS (0)
70 #define _DIGI_MAX_VOLUME (16384)
71 #define MAX_SOUND_OBJECTS 22
72
73
74
75 //      Variables
76 //      ----------------------------------------------------------------------------
77
78 int     Digi_initialized                                = 0;
79 static int      digi_atexit_called      = 0;                                            // Set to 1 if atexit(digi_close) was called
80
81 int digi_sample_rate                                    = SAMPLE_RATE_22K;      // rate to use driver at
82 int digi_max_channels           = 8;
83
84 int digi_total_locks = 0;
85
86 static int digi_volume                          = _DIGI_MAX_VOLUME;     // Max volume
87 static int digi_system_initialized              = 0;
88 static int digi_sound_locks[MAX_SOUNDS];
89 BOOL DIGIDriverInit = FALSE;
90
91
92 // MIDI stuff
93 //      ----------------------------------------------------------------------------
94 WMIDISONG WMidiSong;
95 int             WMidiHandle=0;
96 ubyte           *SongData=NULL;
97 HGLOBAL hSongData=NULL;
98 int             SongSize;
99
100 char digi_last_midi_song[16] = "";
101
102 static BOOL                                                     MIDIDriverInit  = FALSE;
103
104 static int midi_system_initialized      = 0;
105 static int midi_volume                                  = 128/2;        // Max volume
106
107 extern int Redbook_playing;
108
109
110 /* Obsolete */
111 WORD            hSOSDigiDriver = 0xffff;                                // handle for the SOS driver being used 
112 WORD            hSOSMidiDriver = 0xffff;                        // handle for the loaded MIDI driver
113 WORD            hTimerEventHandle = 0xffff;                     // handle for the timer function
114 int digi_driver_dma                                                                                     = 0;
115 int digi_driver_board                                                                           = 0;
116 int digi_driver_port                                                            = 0;
117 int digi_driver_irq                                                             = 0;
118 int digi_midi_type                                                              = 0;
119 int digi_midi_port                                                                                      = 0;
120 LPSTR digi_driver_path = NULL;
121 /* Not Obsolete */
122
123
124 //      Sound Handle stuff
125 //      ----------------------------------------------------------------------------
126 digi_channel channels[MAX_CHANNELS];
127 int next_channel = 0;
128 int channels_inited = 0;
129
130
131 //      Functions
132 //      ----------------------------------------------------------------------------
133 int verify_sound_channel_free(int channel);
134
135 void * digi_load_file( char * szFileName, HGLOBAL *hmem, int * length );
136
137
138
139 //      FUNCTIONS!!!
140 //              DIGI SYSTEM
141 //                      Initialization
142 //                      Play
143 //                      Sound System
144 //
145 //              MIDI SYSTEM
146 //      ----------------------------------------------------------------------------
147
148 int digi_init(void)
149 {
150         int i;
151
152         Digi_initialized = 1;
153
154 //      Perform MIDI Detection
155
156 // Initialize MIDI driver
157         if (! FindArg( "-nomusic" )) {
158                 midi_system_initialized = 1;
159                 if (digi_init_midi()) {
160                         mprintf((1, "Couldn't initialize MIDI system.\n"));
161                         midi_system_initialized = 0;
162                         return 1;
163                 }
164         }
165
166 // Initialize DIGI driver
167         if (! FindArg( "-nosound" )) {
168                 digi_system_initialized = 1;
169                 if (digi_init_digi()) {
170                         mprintf((1, "Couldn't initialize digital sound system.\n"));
171                         digi_close();
172                         return 2;
173                 }
174         }
175                 
176         if (!digi_atexit_called) {
177                 atexit(digi_close);
178                 digi_atexit_called = 1;
179         }
180
181 //      Miscellaneous Initialization
182         digi_init_sounds();
183
184         for (i = 0; i < MAX_SOUNDS; i++)
185                 digi_sound_locks[i] = 0;
186
187         digi_stop_all_channels();
188
189         return 0; 
190 }
191
192
193 void digi_close(void)
194 {
195
196         if (!Digi_initialized) return;
197         Digi_initialized = 0;
198
199         digi_close_midi();
200         digi_close_digi();
201
202         digi_system_initialized = 0;
203         midi_system_initialized = 0;
204 }
205
206
207 int digi_init_digi(void)
208 {
209         SSCaps sscaps;
210
211         Assert(digi_sample_rate == SAMPLE_RATE_11K || digi_sample_rate == SAMPLE_RATE_22K);
212
213         if (!digi_system_initialized) 
214                 return 1;
215
216 //      Determine board type?
217         digi_driver_board = 1;
218
219 //      Initialize Sound System
220         if (!SSInit(_hAppWnd, 32, DSSCL_NORMAL)) {
221                 DIGIDriverInit = FALSE;
222                 return 1;
223         }
224
225         SSGetCaps(&sscaps);
226         if (sscaps.sample_rate < SAMPLE_RATE_22K) 
227                 digi_sample_rate = SAMPLE_RATE_11K;
228
229 //      logentry("Detected sound card using (%d Hz).  Using (%d Hz) samples.\n", sscaps.sample_rate, digi_sample_rate);
230
231 //      Crank up the WAV volume for Wave-Table and full range of FX volumes
232         DIGIDriverInit = TRUE;
233         return 0;
234 }
235
236
237 void digi_close_digi()
238 {
239    if (DIGIDriverInit)   {
240                 SSDestroy();                                                    // resets WAV vol to SSInit value.
241                 DIGIDriverInit = FALSE;
242         }
243 }
244
245
246 int digi_init_midi(void)
247 {
248         DWORD res;
249
250 //      check to see if MIDI is going to be used.
251         if (!midi_system_initialized) 
252                 return 1;
253
254 //      Initialize MIDI system and driver
255         res = wmidi_init(MIDI_MAPPER);
256
257         if (!res) {
258                 MIDIDriverInit = FALSE;
259                 return 1;
260         }
261         else {
262 //@@            switch(sMIDICaps.wTechnology) 
263 //@@            {
264 //@@                    case MOD_SYNTH:
265 //@@                            mprintf((0, "Using SB/SYNTH for MIDI.\n"));     break;
266 //@@
267 //@@                    case MOD_FMSYNTH:
268 //@@                            mprintf((0, "Using ADLIB FM for MIDI.\n")); break;
269 //@@                    
270 //@@                    case MOD_MAPPER:
271 //@@                            mprintf((0, "Using MIDI mapping.\n")); break;
272 //@@
273 //@@                    case MOD_MIDIPORT:
274 //@@                            mprintf((0, "Using SB/External MIDI port.\n")); break;
275 //@@
276 //@@                    case MOD_SQSYNTH:
277 //@@                            mprintf((0, "Using Wave Synthesis for MIDI.\n")); break;
278 //@@
279 //@@                    default:
280 //@@                            mprintf((0, "Using another method (%d) for MIDI.\n", sMIDICaps.wMID)); break;
281 //@@            }
282
283                 digi_midi_type = 1;
284         
285                 MIDIDriverInit = TRUE;
286         }
287
288         digi_set_midi_volume(Config_midi_volume.intval * 16);
289
290         return 0;
291 }               
292
293
294 void digi_close_midi()
295 {
296         if (!midi_system_initialized) return;
297
298         if (MIDIDriverInit)   {
299       if (WMidiHandle)  {
300          // stop the last MIDI song from playing
301                         wmidi_stop();
302                         wmidi_close_song();
303          WMidiHandle = 0;
304       }
305       if (SongData)  {
306                         GlobalUnlock(SongData);
307                         GlobalFree(hSongData);
308          SongData = NULL;
309                         hSongData = NULL;
310       }
311
312                 wmidi_close();
313                 MIDIDriverInit = FALSE;
314    }
315 }
316
317
318 void digi_reset()       
319 {
320         if ( Digi_initialized ) {
321                 digi_stop_all_channels();
322                 digi_close();
323                 mprintf( (0, "Sound system DISABLED.\n" ));
324         } else {
325                 digi_init();
326                 mprintf( (0, "Sound system ENABLED.\n" ));
327         }
328 }
329
330
331 //      Channel Functions
332 //      ----------------------------------------------------------------------------
333
334 void digi_stop_all_channels()
335 {
336         int i;
337
338         for (i=0; i<MAX_CHANNELS; i++ )
339                 digi_stop_sound(i);
340
341         for (i=0; i<MAX_SOUNDS; i++ )   {
342                 Assert( digi_sound_locks[i] == 0 );
343         }
344 }
345
346 void digi_set_max_channels(int n)
347 {
348         digi_max_channels       = n;
349
350         if ( digi_max_channels < 1 ) 
351                 digi_max_channels = 1;
352         if ( digi_max_channels > 32 ) 
353                 digi_max_channels = 32;
354
355         if ( !Digi_initialized ) return;
356         if ( !DIGIDriverInit )  return;
357
358         digi_stop_all_channels();
359 }
360
361 int digi_get_max_channels()
362 {
363         return digi_max_channels;
364 }
365
366 int digi_is_channel_playing( int c )
367 {
368         if (!Digi_initialized) return 0;
369         if (!DIGIDriverInit) return 0;
370
371         if ( channels[c].used && SSChannelPlaying((int)channels[c].handle)) 
372                 return 1;
373         return 0;
374 }
375
376 void digi_set_channel_volume( int c, int volume )
377 {
378         if (!Digi_initialized) return;
379         if (!DIGIDriverInit) return;
380
381         if ( !channels[c].used ) return;
382
383         SSSetChannelVolume(channels[c].handle, (unsigned short)fixmuldiv(volume,digi_volume,F1_0));
384 }
385         
386 void digi_set_channel_pan( int c, int pan )
387 {
388         if (!Digi_initialized) return;
389         if (!DIGIDriverInit) return;
390
391         if ( !channels[c].used ) return;
392
393         SSSetChannelPan(channels[c].handle, (unsigned short)pan);
394 }
395
396 void digi_stop_sound( int c )
397 {
398         if (!Digi_initialized) return;
399         if (!DIGIDriverInit) return;
400
401         if (!channels[c].used) return;
402
403         if ( digi_is_channel_playing(c)  )              {
404                 SSStopChannel(channels[c].handle);
405         }
406         channels[c].used = 0;
407
408         channels[c].soundobj = -1;
409         channels[c].persistant = 0;
410 }
411
412 void digi_end_sound( int c )
413 {
414         if (!Digi_initialized) return;
415         if (!DIGIDriverInit) return;
416
417         if (!channels[c].used) return;
418
419         channels[c].soundobj = -1;
420         channels[c].persistant = 0;
421 }
422
423
424 // Returns the channel a sound number is playing on, or
425 // -1 if none.
426 int digi_find_channel(int soundno)
427 {
428         int i, is_playing;
429
430         if (!Digi_initialized) return -1;
431         if (!DIGIDriverInit) return -1;
432
433         if (soundno < 0 ) return -1;
434         if (GameSounds[soundno].data==NULL) {
435                 Int3();
436                 return -1;
437         }
438
439         is_playing = 0;
440         for (i=0; i<digi_max_channels; i++ )    {
441                 if ( channels[i].used && (channels[i].soundnum==soundno) )
442                         if ( digi_is_channel_playing(i) )
443                                 return i;
444         }       
445         return -1;
446 }
447
448 extern void digi_end_soundobj(int channel);     
449 extern int SoundQ_channel;
450 extern void SoundQ_end();
451
452
453 //      DIGI Start Sample function
454 //      ----------------------------------------------------------------------------
455 int digi_start_sound(short soundnum, fix volume, int pan, int looping, int loop_start, int loop_end, int soundobj)
456 {
457         int i, starting_channel;
458         int sHandle;
459         SSoundBuffer ssb;
460
461         if ( !Digi_initialized ) return -1;
462         if ( !DIGIDriverInit )  return -1;
463
464         Assert(GameSounds[soundnum].data != -1);
465
466         memset(&ssb, 0, sizeof(SSoundBuffer));
467         
468         ssb.data = (char *)GameSounds[soundnum].data;
469         ssb.length = GameSounds[soundnum].length;
470         ssb.pan = (unsigned short)pan+1;
471 //      ssb.id = soundnum;
472         ssb.vol = (unsigned short)fixmuldiv(volume, digi_volume, F1_0);
473         ssb.vol = (ssb.vol << 2);
474         ssb.rate = digi_sample_rate;
475         ssb.channels = 1;
476         ssb.bits_per_sample = 8;
477
478         if (looping) {
479                 ssb.looping = 1;
480                 ssb.loop_start = ssb.loop_end = -1;
481         }       
482         if (loop_start != -1) {
483                 Assert( loop_end != -1);
484                 ssb.loop_start = loop_start;
485                 ssb.loop_end = loop_end;
486                 ssb.loop_length = loop_end - loop_start;
487         }               
488
489         starting_channel = next_channel;
490
491         while(1)        {
492                 if ( !channels[next_channel].used ) break;
493                 
494                 if (!SSChannelPlaying((int)channels[next_channel].handle)) break;
495
496                 if ( !channels[next_channel].persistant )       {
497                         SSStopChannel(channels[next_channel].handle);
498                         break;  // use this channel!    
499                 }
500                 next_channel++;
501                 if ( next_channel >= digi_max_channels )
502                         next_channel = 0;
503                 if ( next_channel == starting_channel ) {
504                         mprintf(( 1, "OUT OF SOUND CHANNELS!!!\n" ));
505                         return -1;
506                 }
507         }
508         if ( channels[next_channel].used )      {
509                 channels[next_channel].used = 0;
510                 if ( channels[next_channel].soundobj > -1 )     {
511                         digi_end_soundobj(channels[next_channel].soundobj);     
512                 }
513                 if (SoundQ_channel==next_channel)
514                         SoundQ_end();
515         }
516
517         sHandle = SSInitChannel(&ssb);
518         if (sHandle == -1) {
519                 mprintf(( 1, "NOT ENOUGH SOUND SLOTS!!!\n" ));
520                 return -1;
521         }
522
523         #ifndef NDEBUG
524         verify_sound_channel_free(next_channel);
525         #endif
526
527         //free up any sound objects that were using this handle
528         for (i=0; i<digi_max_channels; i++ )    {
529                 if ( channels[i].used && (channels[i].handle == sHandle)  )     {
530                         channels[i].used = 0;
531                         if ( channels[i].soundobj > -1 )        {
532                                 digi_end_soundobj(channels[i].soundobj);        
533                         }
534                         if (SoundQ_channel==i)
535                                 SoundQ_end();
536                 }
537         }
538
539         channels[next_channel].used = 1;
540         channels[next_channel].soundnum = soundnum;
541         channels[next_channel].soundobj = soundobj;
542         channels[next_channel].handle = sHandle;
543         channels[next_channel].volume = volume;
544         channels[next_channel].persistant = 0;
545         if ( (soundobj > -1) || (looping) || (volume>F1_0) )
546                 channels[next_channel].persistant = 1;
547
548         i = next_channel;
549         next_channel++;
550         if ( next_channel >= digi_max_channels )
551                 next_channel = 0;
552
553         return i;
554 }
555
556
557 //      Volume Functions
558 //      ----------------------------------------------------------------------------
559 void digi_set_midi_volume( int mvolume )
560 {
561
562         int old_volume = midi_volume;
563
564         if ( mvolume > 127 )
565                 midi_volume = 127;
566         else if ( mvolume < 0 )
567                 midi_volume = 0;
568         else
569                 midi_volume = mvolume;
570
571         if ( (MIDIDriverInit) )         {
572                 if (!Redbook_playing && (old_volume < 1) && ( midi_volume > 1 ) )       {
573                         if (WMidiHandle == 0 )
574                                 digi_play_midi_song( digi_last_midi_song, NULL, NULL, 1 );
575                 }
576                 wmidi_set_volume(midi_volume);
577         }
578
579         mprintf((0, "Changing midi volume=%d.\n", midi_volume));
580 }
581
582 void digi_set_digi_volume( int dvolume )
583 {
584         dvolume = fixmuldiv( dvolume, _DIGI_MAX_VOLUME, 0x7fff);
585         if ( dvolume > _DIGI_MAX_VOLUME )
586                 digi_volume = _DIGI_MAX_VOLUME;
587         else if ( dvolume < 0 )
588                 digi_volume = 0;
589         else
590                 digi_volume = dvolume;
591
592         if ( !Digi_initialized ) return;
593         if ( !digi_system_initialized ) return;
594
595         //digi_sync_sounds();
596 }
597
598
599 // 0-0x7FFF 
600 void digi_set_volume( int dvolume, int mvolume )        
601 {
602         digi_set_midi_volume( mvolume );
603         digi_set_digi_volume( dvolume );
604         mprintf(( 1, "Volume: 0x%x and 0x%x\n", digi_volume, midi_volume ));
605 }
606
607 // allocate memory for file, load fil
608 void * digi_load_file( char * szFileName, HGLOBAL *hmem, int * length )
609 {
610    PSTR  pDataPtr;
611         CFILE * fp;
612         
613    // open file
614    fp  =  cfopen( szFileName, "rb" );
615         if ( !fp ) return NULL;
616
617    *length  =  cfilelength(fp);
618
619         *hmem = GlobalAlloc(GPTR, *length);
620         if (!(*hmem)) return NULL;
621         pDataPtr = GlobalLock(*hmem);
622
623    // read in driver
624    cfread( pDataPtr, *length, 1, fp);
625
626    // close driver file
627    cfclose( fp );
628
629    // return 
630    return( pDataPtr );
631 }
632
633
634 void digi_stop_current_song()
635 {
636         if (!Digi_initialized) return;
637
638         if ( MIDIDriverInit )   {
639                 // Stop last song...
640                 if (WMidiHandle > 0 )   {
641                    // stop the last MIDI song from playing
642                         wmidi_stop();
643                         wmidi_close_song();
644                         WMidiHandle = 0;
645                 }
646                 if (SongData)   {
647                         GlobalUnlock(SongData);
648                         GlobalFree(hSongData);
649                         SongData = NULL;
650                         hSongData = NULL;
651                 }
652         }
653 }
654
655
656 void digi_play_midi_song( char * filename, char * melodic_bank, char * drum_bank, int loop )
657 {
658         char fname[128];
659         CFILE           *fp;
660         int sl;
661
662         if (!Digi_initialized) return;
663         if ( !MIDIDriverInit )  return;
664
665         digi_stop_current_song();
666
667         if ( filename == NULL ) return;
668
669         strcpy( digi_last_midi_song, filename );
670
671         fp = NULL;
672
673         sl = strlen( filename );
674         strcpy( fname, filename );      
675         fname[sl-3] = 'm';
676         fname[sl-2] = 'i';
677         fname[sl-1] = 'd';
678
679         fp = cfopen( fname, "rb" );
680         mprintf((0, "Loading %s\n", fname));
681
682         if ( !fp  )     {
683                 mprintf( (1, "Error opening midi file, '%s'", filename ));
684                 return;
685         }
686         if ( midi_volume < 1 )          {
687                 cfclose(fp);
688                 return;                         // Don't play song if volume == 0;
689         }
690         SongSize = cfilelength( fp );
691         hSongData = GlobalAlloc(GPTR, SongSize);
692         if (hSongData==NULL)    {
693                 cfclose(fp);
694                 mprintf( (1, "Error allocating %d bytes for '%s'", SongSize, filename ));
695                 return;
696         }
697         SongData = GlobalLock(hSongData);
698         if ( cfread (  SongData, SongSize, 1, fp )!=1)  {
699                 mprintf( (1, "Error reading midi file, '%s'", filename ));
700                 cfclose(fp);
701                 GlobalUnlock(SongData);
702                 GlobalFree(hSongData);
703                 SongData=NULL;
704                 hSongData = NULL;
705                 return;
706         }
707
708         cfclose(fp);
709
710 // setup the song initialization structure
711         WMidiSong.data = SongData;
712         WMidiSong.length = SongSize;
713
714         if ( loop )
715                 WMidiSong.looping = 1;
716         else
717                 WMidiSong.looping = 0;
718
719 //      initialize the song
720         WMidiHandle = wmidi_init_song(&WMidiSong);
721         if (!WMidiHandle) {
722                 mprintf((1, "Unable to initialize MIDI song.\n"));              
723                 GlobalUnlock(SongData);
724                 GlobalFree(hSongData);
725                 SongData=NULL;
726                 hSongData = NULL;
727                 return;
728         }
729
730         Assert( WMidiHandle == 1 );
731          
732 // start the song playing
733         mprintf((0, "Playing song %x.\n", WMidiHandle));
734
735         if (!wmidi_play()) {
736                 mprintf( (1, "\nUnable to play midi song.\n"));
737                 wmidi_close_song();
738                 GlobalUnlock(SongData);
739                 GlobalFree(hSongData);
740                 SongData=NULL;
741                 hSongData = NULL;
742                 return;
743    }
744 }
745
746
747 int sound_paused = 0;
748
749 void digi_pause_midi()
750 {
751         if (!Digi_initialized) return;
752
753         if (sound_paused==0)    {
754                 if ( digi_midi_type > 0 && WMidiHandle > 0)     {
755                         // pause here
756                                 wmidi_pause();
757                 }
758         }
759         sound_paused++;
760 }
761
762
763
764 void digi_resume_midi()
765 {
766         if (!Digi_initialized) return;
767
768         Assert( sound_paused > 0 );
769
770         if (sound_paused==1)    {
771                 // resume sound here
772                 if ( digi_midi_type > 0 && WMidiHandle > 0)     {
773                         wmidi_resume();
774                 }
775         }
776         sound_paused--;
777 }
778
779
780 #ifndef NDEBUG
781 void digi_debug()
782 {
783         int i;
784         int n_voices=0;
785
786         if (!Digi_initialized) return;
787         if (!DIGIDriverInit) return;
788
789         for (i=0; i<digi_max_channels; i++ )    {
790                 if ( digi_is_channel_playing(i) )
791                         n_voices++;
792         }
793
794         mprintf_at(( 0, 2, 0, "DIGI: Active Sound Channels: %d/%d ", n_voices, digi_max_channels));
795 }
796
797
798 void digi_midi_debug()
799 {
800
801 }
802         
803 #endif
804
805
806 extern BOOL WMidi_NewStream;
807
808 void digi_midi_wait()
809 {
810         fix ftime;
811         int tech;
812
813         tech = wmidi_get_tech();
814         if (tech) return;
815         
816         ftime = timer_get_fixed_seconds() + 0x50000;
817         WMidi_NewStream = FALSE;
818         while ((WMidi_NewStream < 2 && WMidiHandle) || (timer_get_fixed_seconds() < ftime)) Sleep(0);
819 }
820
821