1 // Emacs style mode select -*- C++ -*-
2 //-----------------------------------------------------------------------------
3 //
4 // $Id: I_sound.c 1471 2019-10-04 08:59:55Z wesleyjohnson $
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: I_sound.c,v $
18 // Revision 1.6 2007/01/29 06:16:03 chiphog
19 // Possible fix for playing raw MIDI lumps for the os2 and win32 builds.
20 //
21 // Revision 1.5 2004/04/18 12:53:42 hurdler
22 // fix Heretic issue with SDL and OS/2
23 //
24 // Revision 1.4 2003/07/13 13:18:59 hurdler
25 //
26 // Revision 1.3 2000/08/16 16:32:27 ydario
27 // Fixed nosound&nomusic parameters
28 //
29 // Revision 1.2 2000/08/10 11:07:51 ydario
30 // Revision 1.1 2000/08/09 11:56:27 ydario
31 // OS/2 specific platform code
32 //
33 //
34 // DESCRIPTION:
35 // System interface for sound.
36 //
37 //-----------------------------------------------------------------------------
38
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <stdarg.h>
42
43 #include <math.h>
44
45 #include <sys/time.h>
46 #include <sys/types.h>
47
48 #include <fcntl.h>
49 #include <unistd.h>
50 #include <sys/ioctl.h>
51
52 #include <io.h>
53 #ifndef X_OK
54 #define X_OK 0
55 #endif
56
57 // do not know why this port does not use the common qmus2mid through buffers
58 //#define MIDI_FILE_TO_FILE
59
60 #include "I_os2.h"
61
62 // Timer stuff. Experimental.
63 #include <time.h>
64 #include <signal.h>
65
66 #include "doomincl.h"
67 // added for 1.27 19990203 by Kin
68 #include "doomstat.h"
69
70 #include "i_system.h"
71 #include "i_sound.h"
72 #include "command.h"
73 #include "s_sound.h"
74 #include "m_argv.h"
75 #include "m_misc.h"
76 #include "w_wad.h"
77 #include "z_zone.h"
78
79
80 #ifdef MIDI_FILE_TO_FILE
81 #include "qmus2mid2.h"
82 #else
83 #include "qmus2mid.h"
84 #define MIDBUFFERSIZE 128*1024L // buffer size for Mus2Midi conversion (ugly code)
85 static char* MidiData_buf; // buffer allocated at program start for Mus2Mid conversion
86 #endif
87 int music_started=0;
88
89 // A quick hack to establish a protocol between
90 // synchronous mix buffer updates and asynchronous
91 // audio writes. Probably redundant with gametic.
92 static int flag = 0;
93
94 // The number of internal mixing channels,
95 // the samples calculated for each mixing step,
96 // the size of the 16bit, 2 hardware channel (stereo)
97 // mixing buffer, and the samplerate of the raw data.
98
99
100 // Needed for calling the actual sound output.
101 #define SAMPLECOUNT 512
102 #define NUM_CHANNELS 8
103 #define CHANNEL_NUM_MASK (NUM_CHANNELS-1)
104 // It is 2 for 16bit, and 2 for two channels.
105 #define BUFMUL 4
106 #define MIXBUFFERSIZE (SAMPLECOUNT*BUFMUL)
107
108 #define SAMPLERATE 11025 // Hz
109 #define SAMPLESIZE 2 // 16bit
110
111 // The actual output device.
112 int audio_fd;
113
114 // The global mixing buffer.
115 // Basically, samples from all active internal channels
116 // are modifed and added, and stored in the buffer
117 // that is submitted to the audio device.
118 signed short mixbuffer[MIXBUFFERSIZE];
119
120 // The channel step amount...
121 unsigned int channelstep[NUM_CHANNELS];
122 // ... and a 0.16 bit remainder of last step.
123 unsigned int channelstepremainder[NUM_CHANNELS];
124
125
126 // The channel data pointers, start and end.
127 unsigned char* channels[NUM_CHANNELS];
128 unsigned char* channelsend[NUM_CHANNELS];
129
130
131 // Time/gametic that the channel started playing,
132 // used to determine oldest, which automatically
133 // has lowest priority.
134 // In case number of active sounds exceeds
135 // available channels.
136 int channelstart[NUM_CHANNELS];
137
138 // The sound in channel handles,
139 // determined on registration,
140 // might be used to unregister/stop/modify,
141 // currently unused.
142 int channelhandles[NUM_CHANNELS];
143
144 // SFX id of the playing sound effect.
145 // Used to catch duplicates (like chainsaw).
146 int channelids[NUM_CHANNELS];
147
148 // Pitch to stepping lookup, unused.
149 int steptable[256];
150
151 // Volume lookups.
152 int vol_lookup[128*256];
153
154 // Hardware left and right channel volume lookup.
155 int* channelleftvol_lookup[NUM_CHANNELS];
156 int* channelrightvol_lookup[NUM_CHANNELS];
157 #ifdef SURROUND_SOUND
158 byte invert_right[NUM_CHANNELS];
159 #endif
160
161
162 //
163 // This function adds a sound to the
164 // list of currently active sounds,
165 // which is maintained as a given number
166 // (eight, usually) of internal channels.
167 // Returns a handle.
168 //
169 // vol : volume, 0..255
170 // sep : separation, +/- 127, SURROUND_SEP special operation
addsfx(int sfxid,int vol,int step,int sep)171 int addsfx( int sfxid, int vol, int step, int sep )
172 {
173 static unsigned short handlenums = 0;
174
175 int i;
176 int slot;
177 int leftvol, rightvol;
178
179 // Chainsaw troubles.
180 // Play these sound effects only one at a time.
181 if (S_sfx[sfxid].flags & SFX_single)
182 {
183 // Loop all channels, check.
184 for (i=0 ; i<NUM_CHANNELS ; i++)
185 {
186 // Active, and using the same SFX?
187 if ( (channels[i])
188 && (channelids[i] == sfxid) )
189 {
190 if( S_sfx[sfxid].flags & SFX_id_fin )
191 return channelhandles[i]; // already have one
192 // Reset.
193 channels[i] = 0;
194 break;
195 }
196 }
197 }
198
199 // Loop all channels to find oldest SFX.
200 slot = 0; // default
201 int oldest = INT_MAX;
202 for (i=0; i<NUM_CHANNELS; i++)
203 {
204 if (channels[i] == 0) // unused
205 {
206 slot = i;
207 break;
208 }
209 if (channelstart[i] < oldest)
210 {
211 slot = i;
212 oldest = channelstart[i];
213 }
214 }
215
216 // Okay, in the less recent channel,
217 // we will handle the new SFX.
218 // Set pointer to raw data.
219 channels[slot] = (unsigned char *) S_sfx[sfxid].data;
220 // Set pointer to end of raw data.
221 channelsend[slot] = channels[slot] + S_sfx[sfxid].length;
222
223 // Set stepping???
224 // Kinda getting the impression this is never used.
225 channelstep[slot] = step;
226 // ???
227 channelstepremainder[slot] = 0;
228 // Should be gametic, I presume.
229 channelstart[slot] = gametic;
230
231 // vol : range 0..255
232 // mix_sfxvolume : range 0..31
233 vol = (vol * mix_sfxvolume) >> 6;
234
235 // Per left/right channel.
236 // x^2 seperation,
237 // adjust volume properly.
238 #ifdef SURROUND_SOUND
239 invert_right[slot] = 0;
240 if( sep == SURROUND_SEP )
241 {
242 // Use a normal sound data for the left channel (with pan left)
243 // and an inverted sound data for the right channel (with pan right)
244 leftvol = rightvol = (vol * (224 * 224)) >> 16; // slight reduction going through panning
245 invert_right[slot] = 1; // invert right channel
246 }
247 else
248 #endif
249 {
250 // Separation, that is, orientation/stereo.
251 // sep : +/- 127, <0 is left, >0 is right
252 sep += 129; // 129 +/- 127 ; ( 1 - 256 )
253 leftvol = vol - ((vol * sep * sep) >> 16);
254 sep = 258 - sep; // 129 +/- 127
255 rightvol = vol - ((vol * sep * sep) >> 16);
256 }
257
258 // Sanity check, clamp volume.
259 if (rightvol < 0 || rightvol > 127)
260 {
261 I_SoftError("rightvol (%d) out of bounds\n", rightvol);
262 rightvol = ( rightvol < 0 ) ? 0 : 127;
263 }
264 if (leftvol < 0 || leftvol > 127)
265 {
266 I_SoftError("leftvol (%d) out of bounds\n", leftvol);
267 leftvol = ( leftvol < 0 ) ? 0 : 127;
268 }
269
270 // Get the proper lookup table piece
271 // for this volume level???
272 channelleftvol_lookup[slot] = &vol_lookup[leftvol*256];
273 channelrightvol_lookup[slot] = &vol_lookup[rightvol*256];
274
275 // Preserve sound SFX id,
276 // e.g. for avoiding duplicates of chainsaw.
277 channelids[slot] = sfxid;
278
279 // Assign current handle number.
280 // Preserved so sounds could be stopped.
281 channelhandles[slot] = slot | ((channelhandles[slot] + NUM_CHANNELS) & ~CHANNEL_NUM_MASK);
282 return channelhandles[slot];
283 }
284
285
286
287
288
289 //
290 // SFX API
291 // Note: this was called by S_Init.
292 // However, whatever they did in the
293 // old DPMS based DOS version, this
294 // were simply dummies in the Linux
295 // version.
296 // See soundserver initdata().
297 //
I_SetChannels()298 void I_SetChannels()
299 {
300 // Init internal lookups (raw data, mixing buffer, channels).
301 // This function sets up internal lookups used during
302 // the mixing process.
303 int i;
304 int j;
305
306 int* steptablemid = steptable + 128;
307
308 printf( "I_SetChannels\n");
309
310 // Okay, reset internal mixing channels to zero.
311 /*for (i=0; i<NUM_CHANNELS; i++)
312 {
313 channels[i] = 0;
314 }*/
315
316 // This table provides step widths for pitch parameters.
317 // I fail to see that this is currently used.
318 for (i=-128 ; i<128 ; i++)
319 steptablemid[i] = (int)(pow(2.0, (i/64.0))*65536.0);
320
321
322 // Generates volume lookup tables
323 // which also turn the unsigned samples
324 // into signed samples.
325 for (i=0 ; i<128 ; i++)
326 for (j=0 ; j<256 ; j++)
327 vol_lookup[i*256+j] = (i*(j-128)*256)/127;
328 }
329
330
I_SetSfxVolume(int volume)331 void I_SetSfxVolume(int volume)
332 {
333 // Identical to DOS.
334 // Basically, this should propagate
335 // the menu/config file setting
336 // to the state variable used in
337 // the mixing.
338
339 // Can use mix_sfxvolume (0..31), or set local volume vars.
340 // mix_sfxvolume = volume;
341 printf( "I_SetSfxVolume %d\n", volume);
342 }
343
344 // MUSIC API - dummy. Some code from DOS version.
I_SetMusicVolume(int volume)345 void I_SetMusicVolume(int volume)
346 {
347 // Internal state variable.
348 //snd_MusicVolume = volume;
349 printf( "I_SetMusicVolume %d\n", volume);
350 // Now set volume on output device.
351 SetMIDIVolume( pmData, volume);
352
353 // Whatever( snd_MusciVolume );
354 }
355
356
357
I_GetSfx(sfxinfo_t * sfx)358 void I_GetSfx (sfxinfo_t* sfx)
359 {
360 unsigned char* sfxdata;
361 unsigned char* paddedsfx;
362 int i;
363 int size;
364 int paddedsize;
365
366 S_GetSfxLump( sfx );
367 if( ! sfx->data ) return;
368 size = sfx->length;
369 sfxdata = (unsigned char*) sfx->data;
370
371 // Pads the sound effect out to the mixing buffer size.
372 // The original realloc would interfere with zone memory.
373 paddedsize = ((size-8 + (SAMPLECOUNT-1)) / SAMPLECOUNT) * SAMPLECOUNT;
374
375 // Allocate from zone memory.
376 paddedsfx = (unsigned char*)Z_Malloc( paddedsize+8, PU_STATIC, 0 );
377 // ddt: (unsigned char *) realloc(sfxdata, paddedsize+8);
378 // This should interfere with zone memory handling,
379 // which does not kick in in the soundserver.
380
381 // Now copy and pad.
382 memcpy( paddedsfx, sfxdata, size );
383 for (i=size ; i<paddedsize+8 ; i++)
384 paddedsfx[i] = 128;
385
386 // Remove the cached lump.
387 Z_Free( sfxdata );
388
389 // Preserve padded length.
390 sfx->length = paddedsize;
391 // Return allocated padded data.
392 sfx->data = (void*) (paddedsfx + 8); // skip header
393 }
394
395
I_FreeSfx(sfxinfo_t * sfx)396 void I_FreeSfx (sfxinfo_t* sfx)
397 {
398 byte* dssfx;
399
400 if( ! VALID_LUMP(sfx->lumpnum) )
401 return;
402
403 // free sample data
404 if(sfx->data)
405 {
406 Z_Free( sfx->data - 8 ); // undo skip header
407 }
408
409 sfx->data = NULL;
410 sfx->lumpnum = NO_LUMP;
411 }
412
413 //
414 // Starting a sound means adding it
415 // to the current list of active sounds
416 // in the internal channels.
417 // As the SFX info struct contains
418 // e.g. a pointer to the raw data,
419 // it is ignored.
420 // As our sound handling does not handle
421 // priority, it is ignored.
422 // Pitching (that is, increased speed of playback)
423 // is set, but currently not used by mixing.
424 //
425 // vol : volume, 0..255
426 // sep : separation, +/- 127, SURROUND_SEP special operation
427 // Return a channel handle.
I_StartSound(sfxid_t sfxid,int vol,int sep,int pitch,int priority)428 int I_StartSound(sfxid_t sfxid, int vol, int sep, int pitch, int priority)
429 {
430
431 if (nosoundfx)
432 return -1;
433
434 // Debug.
435 //printf( "I_StartSound: starting sound %d\n", id );
436
437 // Returns a handle (not used).
438 id = addsfx( id, vol, steptable[pitch], sep );
439
440 // fprintf( stderr, "/handle is %d\n", id );
441
442 return id;
443 }
444
445
446
447 // handle : the handle returned by StartSound.
I_StopSound(int handle)448 void I_StopSound (int handle)
449 {
450 int slot = handle & CHANNEL_NUM_MASK;
451 if (channelhandles[slot] == handle)
452 {
453 channels[i] = 0;
454 }
455 }
456
457
458 // handle : the handle returned by StartSound.
I_SoundIsPlaying(int handle)459 int I_SoundIsPlaying(int handle)
460 {
461 int slot = handle & CHANNEL_NUM_MASK;
462 if( channelhandles[slot] == handle )
463 {
464 return channels[slot] != NULL;
465 }
466 return 0;
467 }
468
469
470
471
472 //
473 // This function loops all active (internal) sound
474 // channels, retrieves a given number of samples
475 // from the raw sound data, modifies it according
476 // to the current (internal) channel parameters,
477 // mixes the per channel samples into the global
478 // mixbuffer, clamping it to the allowed range,
479 // and sets up everything for transferring the
480 // contents of the mixbuffer to the (two)
481 // hardware channels (left and right, that is).
482 //
483 // This function currently supports only 16bit.
484 //
I_UpdateSound(void)485 void I_UpdateSound( void )
486 {
487
488 // Mix current sound data.
489 // Data, from raw sound, for right and left.
490 register unsigned int sample;
491 register int dl;
492 register int dr;
493
494 // Pointers in global mixbuffer, left, right, end.
495 signed short* leftout;
496 signed short* rightout;
497 signed short* leftend;
498 // Step in mixbuffer, left and right, thus two.
499 int step;
500
501 // Mixing channel index.
502 int chan;
503
504 // Left and right channel
505 // are in global mixbuffer, alternating.
506 leftout = pmData->MixBuffers[ pmData->FillBuffer].pBuffer;
507 rightout = leftout+1;// pmData->BufferParms.ulBufferSize/2;
508 // next fill buffer
509 pmData->FillBuffer++;
510 if (pmData->FillBuffer >= pmData->BufferParms.ulNumBuffers)
511 pmData->FillBuffer = 0;
512 step = 2;
513
514 // Determine end, for left channel only
515 // (right channel is implicit).
516 // ulBufferSize is len in bytes (8 bit), ulBufferSize/2 is 16bit length
517 leftend = leftout + pmData->BufferParms.ulBufferSize/2;
518
519 // Mix sounds into the mixing buffer.
520 // Loop over step*SAMPLECOUNT,
521 // that is 512 values for two channels.
522 while (leftout != leftend)
523 {
524 // Reset left/right value.
525 dl = 0;
526 dr = 0;
527
528 // Love thy L2 chache - made this a loop.
529 // Now more channels could be set at compile time
530 // as well. Thus loop those channels.
531 for ( chan = 0; chan < NUM_CHANNELS; chan++ )
532 {
533 // Check channel, if active.
534 if (channels[ chan ])
535 {
536 //printf( "I_UpdateSound: channel %d active\n", chan);
537
538 // Get the raw data from the channel.
539 sample = *channels[ chan ];
540 // Add left and right part
541 // for this channel (sound)
542 // to the current data.
543 // Adjust volume accordingly.
544 dl += channelleftvol_lookup[ chan ][sample];
545 #ifdef SURROUND_SOUND
546 if( chp->invert_right )
547 dr -= channelrightvol_lookup[ chan ][sample];
548 else
549 dr += channelrightvol_lookup[ chan ][sample];
550 #else
551 dr += channelrightvol_lookup[ chan ][sample];
552 #endif
553 // Increment index ???
554 channelstepremainder[ chan ] += channelstep[ chan ];
555 // MSB is next sample???
556 channels[ chan ] += channelstepremainder[ chan ] >> 16;
557 // Limit to LSB???
558 channelstepremainder[ chan ] &= 65536-1;
559
560 // Check whether we are done.
561 if (channels[ chan ] >= channelsend[ chan ])
562 channels[ chan ] = 0;
563 }
564 }
565
566 // Clamp to range. Left hardware channel.
567 // Has been char instead of short.
568 // if (dl > 127) *leftout = 127;
569 // else if (dl < -128) *leftout = -128;
570 // else *leftout = dl;
571
572 //dl <<= 4;
573 //dr <<= 4;
574
575 if (dl > 0x7fff)
576 *leftout = 0x7fff;
577 else if (dl < -0x8000)
578 *leftout = -0x8000;
579 else
580 *leftout = dl;
581
582 // Same for right hardware channel.
583 if (dr > 0x7fff)
584 *rightout = 0x7fff;
585 else if (dr < -0x8000)
586 *rightout = -0x8000;
587 else
588 *rightout = dr;
589
590 // Increment current pointers in mixbuffer.
591 leftout += step;
592 rightout += step;
593 /*
594 // mono out
595 *leftout = (dl+dr)/2;
596 leftout++;
597 rightout++;
598 */
599 }
600
601 }
602
603
604 //
605 // This would be used to write out the mixbuffer
606 // during each game loop update.
607 // Updates sound buffer and audio device at runtime.
608 // It is called during Timer interrupt with SNDINTR.
609 // Mixing now done synchronous, and
610 // only output be done asynchronous?
611 //
I_SubmitSound(void)612 void I_SubmitSound(void)
613 {
614 // Write it to DSP device.
615 write(audio_fd, mixbuffer, SAMPLECOUNT*BUFMUL);
616 }
617
618
619
620 // You need the handle returned by StartSound.
I_UpdateSoundParams(int handle,int vol,int sep,int pitch)621 void I_UpdateSoundParams( int handle, int vol, int sep, int pitch)
622 {
623 // I fail too see that this is used.
624 // Would be using the handle to identify
625 // on which channel the sound might be active,
626 // and resetting the channel parameters.
627
628 // UNUSED.
629 handle = vol = sep = pitch = 0;
630 }
631
632
633
634
I_ShutdownSound(void)635 void I_ShutdownSound(void)
636 {
637 // Wait till all pending sounds are finished.
638 int done = 0;
639 int i;
640
641 //added:03-01-98:
642 if( !sound_started )
643 return;
644
645 // FIXME (below).
646 printf( "I_ShutdownSound: NOT finishing pending sounds\n");
647
648 while ( !done )
649 {
650 for( i=0 ; i<8 && !channels[i] ; i++);
651
652 // FIXME. No proper channel output.
653 //if (i==8)
654 done=1;
655 DosSleep( 100); // wait 0.1 sec
656 }
657
658 ShutdownDART( pmData);
659
660 // Done.
661 sound_started = false;
662 return;
663 }
664
665
I_StartupSound()666 void I_StartupSound()
667 {
668 int i;
669
670 if (nosoundfx)
671 return;
672
673 // init dart audio
674 InitDART( pmData);
675
676 // Secure and configure sound device first.
677
678 // Initialize external data (all sounds) at start, keep static.
679 printf( "I_InitSound\n");
680
681 // Now initialize mixbuffer with zero.
682 for ( i = 0; i< MIXBUFFERSIZE; i++ )
683 mixbuffer[i] = 0;
684
685 I_SetChannels();
686
687 // Finished initialization.
688 printf( "I_InitSound: sound module ready\n");
689
690 //added:08-01-98:we use a similar startup/shutdown scheme as Allegro.
691 I_AddExitFunc(I_ShutdownSound);
692 sound_started = true;
693
694 }
695
696
697
698
699 //
700 // MUSIC API.
701 // Still no music done.
702 // Remains. Dummies.
703 //
I_InitMusic(void)704 void I_InitMusic(void)
705 {
706 printf( "I_InitMusic\n");
707
708 if (nomusic)
709 return;
710 #ifdef MIDI_FILE_TO_FILE
711 #else
712 // initialisation of midicard by I_StartupSound
713 MidiData_buf = (char *)Z_Malloc (MIDBUFFERSIZE,PU_STATIC,NULL);
714 #endif
715
716 I_AddExitFunc(I_ShutdownMusic);
717 music_started = true;
718 }
719
I_ShutdownMusic(void)720 void I_ShutdownMusic(void)
721 {
722 printf( "I_ShutdownMusic\n");
723
724 if (!music_started)
725 return;
726
727 I_StopSong( 0);
728 I_UnRegisterSong( 0);
729
730 music_started=false;
731 }
732
I_PlaySong(int handle,int looping)733 void I_PlaySong(int handle, int looping)
734 {
735 if (nomusic)
736 return;
737
738 printf( "I_PlaySong looping=%d\n", looping);
739 PlayMIDI( pmData, looping);
740 // need to set volume again, because before midi device was closed
741 SetMIDIVolume( pmData, cv_musicvolume.value);
742 }
743
I_PauseSong(int handle)744 void I_PauseSong (int handle)
745 {
746 if (nomusic)
747 return;
748
749 PauseMIDI( pmData);
750 }
751
I_ResumeSong(int handle)752 void I_ResumeSong (int handle)
753 {
754 if (nomusic)
755 return;
756
757 // UNUSED.
758 handle = 0;
759 ResumeMIDI( pmData);
760 }
761
I_StopSong(int handle)762 void I_StopSong(int handle)
763 {
764 if (nomusic)
765 return;
766
767 // UNUSED.
768 ShutdownMIDI( pmData);
769 }
770
I_UnRegisterSong(int handle)771 void I_UnRegisterSong(int handle)
772 {
773 if (nomusic)
774 return;
775
776 // UNUSED.
777 handle = 0;
778 printf( "I_UnRegisterSong\n");
779 // remove files
780 unlink( "doom.mid");
781 unlink( "doom.mus");
782 }
783
784 // ---------------
785 // I_SaveMemToFile
786 // Save as much as iLength bytes starting at pData, to
787 // a new file of given name. The file is overwritten if it is present.
788 // ---------------
I_SaveMemToFile(unsigned char * pData,unsigned long iLength,char * sFileName)789 void I_SaveMemToFile (unsigned char* pData, unsigned long iLength, char* sFileName)
790 {
791 int fileHandle;
792
793 fileHandle = open( sFileName, O_CREAT | O_BINARY | O_TRUNC | O_WRONLY,
794 S_IWRITE);
795 if (fileHandle == -1)
796 {
797 I_Error ("SaveMemToFile");
798 }
799 write( fileHandle, pData, iLength);
800 close( fileHandle);
801 }
802
I_RegisterSong(void * data,int len)803 int I_RegisterSong(void* data, int len)
804 {
805 int er;
806 char* MidiData = NULL; // MIDI music buffer to be played or NULL
807 unsigned long MidiSize; // size of Midi output data
808 // FILE* blah;
809
810 if (nomusic)
811 return 1;
812
813 #ifdef MIDI_FILE_TO_FILE
814 I_SaveMemToFile (data, len, "doom.mus");
815 qmus2mid_file( "doom.mus", "doom.mid", 0, 89,64,1);
816 #else
817
818 #ifdef DEBUGMIDISTREAM
819 CONS_Printf("I_RegisterSong: \n");
820 #endif
821 if (!memcmp(data,"MUS",3))
822 {
823 // convert mus to mid with a wonderful function
824 // thanks to S.Bacquet for the sources of qmus2mid
825 // convert mus to mid and load it in memory
826 er = qmus2mid((char *)data, 89, 0, len, MIDBUFFERSIZE,
827 /*INOUT*/ MidiData_buf, &MidiSize);
828 if( er != QM_success )
829 {
830 CONS_Printf("Cannot convert mus to mid, converterror :%d\n", er);
831 return 0;
832 }
833 MidiData = MidiData_buf;
834 }
835 else if (!memcmp(data,"MThd",4))
836 {
837 // support mid file in WAD !!! (no conversion needed)
838 MidiData = data;
839 MidiSize = len;
840 }
841 else
842 {
843 CONS_Printf ("Music lump is not MID or MUS music format\n");
844 return 0;
845 }
846
847 if (MidiData == NULL)
848 {
849 CONS_Printf ("Not a valid MIDI file : %c%c%c%c\n",
850 (char)data[0], (char)data[1], (char)data[2], (char)data[3]);
851 return 0;
852 }
853 #ifdef DEBUGMIDISTREAM
854 else
855 {
856 I_SaveMemToFile (MidiData, MidiSize, "c:/temp/debug.mid");
857 }
858 #endif
859 I_SaveMemToFile (MidiData, MidiSize, "doom.mid");
860 #endif
861
862 OpenMIDI( pmData);
863
864 return 1;
865 }
866
867 // Is the song playing?
I_QrySongPlaying(int handle)868 int I_QrySongPlaying(int handle)
869 {
870 // UNUSED.
871 handle = 0;
872 printf( "I_QrySongPlaying\n");
873
874 return 0;
875 }
876
877 #ifdef FMOD_SOUND
878 //Hurdler: TODO
I_StartFMODSong()879 void I_StartFMODSong()
880 {
881 CONS_Printf("I_StartFMODSong: Not yet supported under OS/2.\n");
882 }
883
I_StopFMODSong()884 void I_StopFMODSong()
885 {
886 CONS_Printf("I_StopFMODSong: Not yet supported under OS/2.\n");
887 }
I_SetFMODVolume(int volume)888 void I_SetFMODVolume(int volume)
889 {
890 CONS_Printf("I_SetFMODVolume: Not yet supported under OS/2.\n");
891 }
892 #endif
893