1 /*
2  * OpenBOR - http://www.chronocrash.com
3  * -----------------------------------------------------------------------
4  * All rights reserved, see LICENSE in OpenBOR root for details.
5  *
6  * Copyright (c) 2004 - 2014 OpenBOR Team
7  */
8 
9 /*
10 **	Sound mixer.
11 **	High quality, with support for ADPCM and Vorbis-compressed music.
12 **
13 **	Also plays WAV files (both 8-bit and 16-bit).
14 **	Note: 8-bit wavs are unsigned, 16-bit wavs are signed!!!
15 **
16 **
17 **	Function naming convention:
18 **	- Public functions start with "sound_"
19 **	- Music-related functions end with "_music"
20 **	- Soundeffect-related functions end with "_sample"
21 **
22 **
23 **	To do:
24 **	- I think it's stable now, but stay alert!
25 **	- test 16-bit soundfx
26 **
27 **
28 **	Note:
29 **  If any of the #defines are increased in size
30 **  pay close attention to the the size of variables
31 **  which are used in conjunction with it.  You could
32 **  be going beyond the variable's current size which
33 **  will cause errors!!!
34 */
35 
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 /*
40 Caution: move vorbis headers here otherwise the structs will
41  get poisoned by #pragma in other header files, i.e. list.h
42 */
43 #ifdef DC
44 #include <ivorbisfile.h>
45 #elif TREMOR
46 #include <tremor/ivorbisfile.h>
47 #else
48 #include <vorbis/vorbisfile.h>
49 #endif
50 #include "soundmix.h"
51 #include "globals.h"
52 #include "adpcm.h"
53 #include "sblaster.h"
54 #include "borendian.h"
55 #include "List.h"
56 
57 
58 #define		MIXSHIFT		     3	    // 2 should be OK
59 #define		MAXVOLUME		     64	    // 64 for backw. compat.
60 //#define		MAX_SAMPLES		     1024	// Should be well enough
61 #define		MAX_CHANNELS	     64	    // Should be well enough
62 
63 // Hardware settings for SoundBlaster (change only if latency is too big)
64 #define		SB_BUFFER_SIZE		 0x8000
65 #define		SB_BUFFER_SIZE_MASK	 0x7FFF
66 #define		SB_WBUFFER_SIZE		 0x4000
67 #define		SB_WBUFFER_SIZE_MASK 0x3FFF
68 #define		MIXBUF_SIZE		     SB_BUFFER_SIZE*8
69 #define		PREMIX_SIZE		     1024
70 #define		MIX_BLOCK_SIZE		 32
71 
72 #ifndef DC
73 #pragma pack(4)
74 #endif
75 
76 typedef struct
77 {
78     int            active;		 // 1 = play, 2 = loop
79     int				paused;
80     int            samplenum;	 // Index of sound playing
81     unsigned int   priority;	 // Used for SFX
82     int				playid;
83     int            volume[2];	 // Stereo :)
84     int            channels;
85     unsigned int   fp_samplepos; // Position (fixed-point)
86     unsigned int   fp_period;	 // Period (fixed-point)
87 } channelstruct;
88 
89 typedef struct
90 {
91     void 		   *sampleptr;
92     int			   soundlen;	 // Length in samples
93     int            bits;		 // 8/16 bit
94     int            frequency;    // 11025 * 1,2,4
95     int            channels;
96 } samplestruct;
97 
98 typedef struct
99 {
100     samplestruct  sample;
101     int index;
102     char *filename;
103 } s_soundcache;
104 
105 
106 static List samplelist;
107 static s_soundcache *soundcache = NULL;
108 static int sound_cached = 0;
109 int sample_play_id = 0;
110 static channelstruct vchannel[MAX_CHANNELS];
111 musicchannelstruct musicchannel;
112 static s32 *mixbuf = NULL;
113 static int playbits;
114 int playfrequency;
115 static int max_channels = 0;
116 
117 // Indicates whether the hardware is playing, and if mixing is active
118 static int mixing_active = 0;
119 
120 // Indicates whether the sound system is initialized
121 static int mixing_inited = 0;
122 
123 // Counts the total number of samples played
124 static u32 samplesplayed;
125 
126 // Records type of currently playing music: 0=ADPCM, 1=Vorbis
127 static int music_type = 0;
128 
129 //////////////////////////////// WAVE LOADER //////////////////////////////////
130 
131 #ifndef DC
132 #pragma pack(push, 1)
133 #endif
134 
135 
136 #define		HEX_RIFF	0x46464952
137 #define		HEX_WAVE	0x45564157
138 #define		HEX_fmt		0x20746D66
139 #define		HEX_data	0x61746164
140 #define		FMT_PCM		0x0001
141 
loadwave(char * filename,char * packname,samplestruct * buf,unsigned int maxsize)142 static int loadwave(char *filename, char *packname, samplestruct *buf, unsigned int maxsize)
143 {
144     struct
145     {
146         u32				riff;
147         u32				size;
148         u32				type;
149     } riffheader;
150     struct
151     {
152         u32				tag;
153         u32				size;
154     } rifftag;
155     struct
156     {
157         u16				format;		// 1 = PCM
158         u16				channels;	// Mono, stereo
159         u32				samplerate;	// 11025, 22050, 44100
160         u32				bps;		// Bytes/second
161         u16				unknown;
162         u16				samplebits;	// 8, 12, 16
163     } fmt;
164 
165     int handle;
166     int mulbytes;
167 
168     if(buf == NULL)
169     {
170         return 0;
171     }
172 
173     if((handle = openpackfile(filename, packname)) == -1)
174     {
175         return 0;
176     }
177     if(readpackfile(handle, &riffheader, sizeof(riffheader)) != sizeof(riffheader))
178     {
179         closepackfile(handle);
180         return 0;
181     }
182 
183     riffheader.riff = SwapLSB32(riffheader.riff);
184     riffheader.size = SwapLSB32(riffheader.size);
185     riffheader.type = SwapLSB32(riffheader.type);
186 
187     if(riffheader.riff != HEX_RIFF || riffheader.type != HEX_WAVE)
188     {
189         closepackfile(handle);
190         return 0;
191     }
192 
193     rifftag.tag = 0;
194     // Search for format tag
195     while(rifftag.tag != HEX_fmt)
196     {
197         if(readpackfile(handle, &rifftag, sizeof(rifftag)) != sizeof(rifftag))
198         {
199             closepackfile(handle);
200             return 0;
201         }
202         rifftag.tag = SwapLSB32(rifftag.tag);
203         rifftag.size = SwapLSB32(rifftag.size);
204         if(rifftag.tag != HEX_fmt)
205         {
206             seekpackfile(handle, rifftag.size, SEEK_CUR);
207         }
208     }
209     if(readpackfile(handle, &fmt, sizeof(fmt)) != sizeof(fmt))
210     {
211         closepackfile(handle);
212         return 0;
213     }
214 
215     fmt.format = SwapLSB16(fmt.format);
216     fmt.channels = SwapLSB16(fmt.channels);
217     fmt.unknown = SwapLSB16(fmt.unknown);
218     fmt.samplebits = SwapLSB16(fmt.samplebits);
219     fmt.samplerate = SwapLSB32(fmt.samplerate);
220     fmt.bps = SwapLSB32(fmt.bps);
221 
222     if(rifftag.size > sizeof(fmt))
223     {
224         seekpackfile(handle, rifftag.size - sizeof(fmt), SEEK_CUR);
225     }
226 
227     if(fmt.format != FMT_PCM || (fmt.channels != 1 && fmt.channels != 2) || (fmt.samplebits != 8 && fmt.samplebits != 16))
228     {
229         closepackfile(handle);
230         return 0;
231     }
232     mulbytes = (fmt.samplebits == 16 ? 2 : 1);
233 
234 
235     // Search for data tag
236     while(rifftag.tag != HEX_data)
237     {
238         if(readpackfile(handle, &rifftag, sizeof(rifftag)) != sizeof(rifftag))
239         {
240             closepackfile(handle);
241             return 0;
242         }
243         rifftag.tag = SwapLSB32(rifftag.tag);
244         rifftag.size = SwapLSB32(rifftag.size);
245         if(rifftag.tag != HEX_data)
246         {
247             seekpackfile(handle, rifftag.size, SEEK_CUR);
248         }
249     }
250 
251     if(rifftag.size < maxsize)
252     {
253         maxsize = rifftag.size;
254     }
255     if((buf->sampleptr = malloc(maxsize + 8)) == NULL)
256     {
257         closepackfile(handle);
258         return 0;
259     }
260     if(fmt.samplebits == 8)
261     {
262         memset(buf->sampleptr, 0x80, maxsize + 8);
263     }
264     else
265     {
266         memset(buf->sampleptr, 0x80, maxsize + 8);
267     }
268 
269     if( readpackfile(handle, buf->sampleptr, maxsize) != (int)maxsize)
270     {
271         if(buf->sampleptr != NULL)
272         {
273             free(buf->sampleptr);
274             buf->sampleptr = NULL;
275         }
276         closepackfile(handle);
277         return 0;
278     }
279 
280     closepackfile(handle);
281 
282     buf->soundlen = maxsize / mulbytes;
283     buf->bits = fmt.samplebits;
284     buf->frequency = fmt.samplerate;
285     buf->channels = fmt.channels;
286 
287     return maxsize;
288 }
289 
sound_reload_sample(int index)290 int sound_reload_sample(int index)
291 {
292     if(!mixing_inited)
293     {
294         return 0;
295     }
296     if(index < 0 || index >= sound_cached)
297     {
298         return 0;
299     }
300     if(!soundcache[index].sample.sampleptr)
301     {
302         //printf("packfile: '%s'\n", packfile);
303         return loadwave(soundcache[index].filename, packfile, &(soundcache[index].sample), MAX_SOUND_LEN);
304     }
305     else
306     {
307         return 1;
308     }
309 }
310 
311 
312 // Load a sound or return index
sound_load_sample(char * filename,char * packfilename,int iLog)313 int sound_load_sample(char *filename, char *packfilename, int iLog)
314 {
315     s_soundcache *cache;
316     samplestruct sample;
317     static char convcache[256];
318     if(!mixing_inited)
319     {
320         return -1;
321     }
322     /////////////////////////////
323     strcpy(convcache, filename);
324     lc(convcache, strlen(convcache));
325     if(List_FindByName(&samplelist, convcache))
326     {
327         cache = &soundcache[(size_t)List_Retrieve(&samplelist)];
328         if(!cache->sample.sampleptr)
329         {
330             if(!sound_reload_sample(cache->index) && iLog)
331             {
332                 printf("sound_load_sample can't restore sampleptr from file '%s'!\n", filename);
333             }
334         }
335         return cache->index;
336     }
337 
338     memset(&sample, 0, sizeof(sample));
339     if(!loadwave(filename, packfilename, &sample, MAX_SOUND_LEN))
340     {
341         if(iLog)
342         {
343             printf("sound_load_sample can't load sample from file '%s'!\n", filename);
344         }
345         return -1;
346     }
347 
348     __realloc(soundcache, sound_cached);
349     soundcache[sound_cached].sample = sample;
350 
351     List_GotoLast(&samplelist);
352     List_InsertAfter(&samplelist, (void *)(size_t)sound_cached, convcache);
353     soundcache[sound_cached].index = sound_cached;
354     soundcache[sound_cached].filename = List_GetName(&samplelist);
355 
356     sound_cached++;
357     return sound_cached - 1;
358 
359 }
360 
361 // Changed to conserve memory: added this function
sound_unload_sample(int index)362 void sound_unload_sample(int index)
363 {
364     if(!mixing_inited)
365     {
366         return;
367     }
368     if(index < 0 || index >= sound_cached)
369     {
370         return;
371     }
372     if(soundcache[index].sample.sampleptr != NULL)
373     {
374         free(soundcache[index].sample.sampleptr);
375         soundcache[index].sample.sampleptr = NULL;
376         memset(&soundcache[index].sample, 0, sizeof(samplestruct));
377     }
378 }
379 
sound_unload_all_samples()380 void sound_unload_all_samples()
381 {
382     int i;
383     if(!soundcache)
384     {
385         return;
386     }
387     for(i = 0; i < sound_cached; i++)
388     {
389         sound_unload_sample(i);
390     }
391     List_Clear(&samplelist);
392     free(soundcache);
393     soundcache = NULL;
394     sound_cached = 0;
395 }
396 
397 #ifndef DC
398 #pragma pack(pop)
399 #endif
400 
401 /////////////////////////////// Mix to DMA //////////////////////////////////
402 // Mixbuffer / DMA buffer data handling
403 // Writes mixbuffer data (16-bit mixed in 32-bit array)
404 // to 8-bit or 16-bit DMA buffer.
405 
406 // Fill the mixbuffer with silence
clearmixbuffer(unsigned int * buf,int n)407 static void clearmixbuffer(unsigned int *buf, int n)
408 {
409     while((--n) >= 0)
410     {
411         *buf = 0x8000 << MIXSHIFT;
412         ++buf;
413     }
414 }
415 
416 
417 /////////////////////////////////// Mixers ///////////////////////////////////
418 // Mixers: mix (16-bit) in the mixbuffer, then write to DMA memory (see above).
419 // The mixing code handles fixed-point conversion and looping.
420 
421 // Input: number of input samples to mix
mixaudio(unsigned int todo)422 static void mixaudio(unsigned int todo)
423 {
424 
425     static int i, chan, lvolume, rvolume, lmusic, rmusic;
426     static unsigned int fp_pos, fp_period, fp_len, fp_playto;
427     static int snum;
428     static unsigned char *sptr8;
429     static short *sptr16;
430 
431     // First mix the music, if playing
432     if(musicchannel.active && !musicchannel.paused)
433     {
434 
435         sptr16 = musicchannel.buf[musicchannel.playing_buffer];
436         fp_playto = musicchannel.fp_playto[musicchannel.playing_buffer];
437         fp_pos = musicchannel.fp_samplepos;
438         fp_period = musicchannel.fp_period;
439         lvolume = musicchannel.volume[0];
440         rvolume = musicchannel.volume[1];
441 
442         // Mix it
443         for(i = 0; i < (int)todo;)
444         {
445 
446             // Reached end of playable area,
447             // switch buffers or stop
448             if(fp_pos >= fp_playto)
449             {
450                 // Done playing this one
451                 musicchannel.fp_playto[musicchannel.playing_buffer] = 0;
452                 // Advance to next buffer
453                 musicchannel.playing_buffer++;
454                 musicchannel.playing_buffer %= MUSIC_NUM_BUFFERS;
455                 // Correct position in next buffer
456                 fp_pos = fp_pos - fp_playto;
457                 // Anything to play?
458                 if(fp_pos < musicchannel.fp_playto[musicchannel.playing_buffer])
459                 {
460                     // Yeah, switch!
461                     sptr16 = musicchannel.buf[musicchannel.playing_buffer];
462                     fp_playto = musicchannel.fp_playto[musicchannel.playing_buffer];
463                 }
464                 else
465                 {
466                     // Nothing more to do
467                     // Also disable this buffer, just incase
468                     musicchannel.fp_playto[musicchannel.playing_buffer] = 0;
469                     fp_pos = 0;
470                     musicchannel.active = 0;
471                     // End for
472                     break;
473                 }
474             }
475 
476             // Mix a sample
477             lmusic = rmusic = sptr16[FIX_TO_INT(fp_pos)];
478             lmusic = (lmusic * lvolume / MAXVOLUME);
479             rmusic = (rmusic * rvolume / MAXVOLUME);
480             mixbuf[i++] += lmusic;
481             if(musicchannel.channels == SOUND_MONO)
482             {
483                 mixbuf[i++] += rmusic;
484             }
485             fp_pos += fp_period;
486         }
487         musicchannel.fp_samplepos = fp_pos;
488     }
489 
490 
491     for(chan = 0; chan < max_channels; chan++)
492     {
493         if(vchannel[chan].active && !vchannel[chan].paused)
494         {
495             unsigned modlen;
496             snum = vchannel[chan].samplenum;
497             if(!soundcache[snum].sample.sampleptr)
498             {
499                 vchannel[chan].active = 0;
500                 continue;
501             }
502             modlen = soundcache[snum].sample.soundlen;
503             fp_len = INT_TO_FIX(soundcache[snum].sample.soundlen);
504             fp_pos = vchannel[chan].fp_samplepos;
505             fp_period = vchannel[chan].fp_period;
506             lvolume = vchannel[chan].volume[0];
507             rvolume = vchannel[chan].volume[1];
508             if(fp_len < 1)
509             {
510                 fp_len = 1;
511             }
512             if(modlen < 1)
513             {
514                 modlen = 1;
515             }
516             if(soundcache[snum].sample.bits == 8)
517             {
518                 sptr8 = soundcache[snum].sample.sampleptr;
519                 for(i = 0; i < (int)todo;)
520                 {
521                     lmusic = rmusic = sptr8[FIX_TO_INT(fp_pos)];
522                     mixbuf[i++] += ((lmusic << 8) * lvolume / MAXVOLUME) - 0x8000;
523                     if(vchannel[chan].channels == SOUND_MONO)
524                     {
525                         mixbuf[i++] += ((rmusic << 8) * rvolume / MAXVOLUME) - 0x8000;
526                     }
527                     fp_pos += fp_period;
528 
529                     // Reached end of sample, stop or loop
530                     if(fp_pos >= fp_len)
531                     {
532                         fp_pos %= fp_len; // = INT_TO_FIX(0);
533                         if(vchannel[chan].active != CHANNEL_LOOPING)
534                         {
535                             vchannel[chan].active = 0;
536                             break;
537                         }
538                     }
539                 }
540             }
541             else if(soundcache[snum].sample.bits == 16)
542             {
543                 sptr16 = soundcache[snum].sample.sampleptr;
544                 for(i = 0; i < (int)todo;)
545                 {
546                     lmusic = rmusic = sptr16[FIX_TO_INT(fp_pos)];
547                     mixbuf[i++] += (lmusic * lvolume / MAXVOLUME);
548                     if(vchannel[chan].channels == SOUND_MONO)
549                     {
550                         mixbuf[i++] += (rmusic * rvolume / MAXVOLUME);
551                     }
552                     fp_pos += fp_period;
553 
554                     // Reached end of sample, stop or loop
555                     if(fp_pos >= fp_len)
556                     {
557                         fp_pos %= fp_len; // = INT_TO_FIX(0);
558                         if(vchannel[chan].active != CHANNEL_LOOPING)
559                         {
560                             vchannel[chan].active = 0;
561                             break;
562                         }
563                     }
564                 }
565             }
566             vchannel[chan].fp_samplepos = fp_pos;
567         }
568     }
569 }
570 
571 //////////////////////////////// ISR ///////////////////////////////////
572 // Called by Soundblaster ISR
573 
update_sample(unsigned char * buf,int size)574 void update_sample(unsigned char *buf, int size)
575 {
576     int i, u, todo = size;
577     if (playbits == 16)
578     {
579         todo >>= 1;
580     }
581 
582     clearmixbuffer((unsigned int *)mixbuf, todo);
583     mixaudio(todo);
584     samplesplayed += (todo >> 1);
585 
586     if (playbits == 8)
587     {
588         unsigned char *dst = buf;
589         for(i = 0; i < todo; i++)
590         {
591             u = mixbuf[i] >> (MIXSHIFT + 8);
592             if (u < 0)
593             {
594                 u = 0;
595             }
596             else if (u > 0xff)
597             {
598                 u = 0xff;
599             }
600             dst[i] = u;
601         }
602     }
603     else
604     {
605         unsigned short *dst = (unsigned short *)buf;
606         for(i = 0; i < todo; i++)
607         {
608             u = mixbuf[i] >> MIXSHIFT;
609             if (u < 0)
610             {
611                 u = 0;
612             }
613             else if (u > 0xffff)
614             {
615                 u = 0xffff;
616             }
617             u ^= 0x8000;
618             dst[i] = u;
619         }
620     }
621 }
622 
623 ////////////////////////// Sound effects control /////////////////////////////
624 // Functions to start, stop, loop, etc.
625 
626 // Speed in percents of normal.
627 // Returns channel the sample is played on or -1 if not playing.
sound_play_sample(int samplenum,unsigned int priority,int lvolume,int rvolume,unsigned int speed)628 int sound_play_sample(int samplenum, unsigned int priority, int lvolume, int rvolume, unsigned int speed)
629 {
630 
631     int i;
632     unsigned int prio_low;
633     int channel;
634 
635     if(!mixing_inited)
636     {
637         return -1;
638     }
639     if(samplenum < 0 || samplenum >= sound_cached)
640     {
641         return -1;
642     }
643     if(speed < 1)
644     {
645         speed = 100;
646     }
647     if(!soundcache[samplenum].sample.sampleptr &&
648             !sound_reload_sample(samplenum))
649     {
650         return -1;
651     }
652 
653     // Try to find unused SFX channel
654     channel = -1;
655     for(i = 0; i < max_channels; i++)
656     {
657         if(!vchannel[i].active)
658         {
659             channel = i;
660         }
661     }
662 
663     if(channel == -1)
664     {
665         // Find SFX channel with lowest current priority
666         for(i = 0, prio_low = 0xFFFFFFFF; i < max_channels; i++)
667         {
668             if(vchannel[i].priority < prio_low)
669             {
670                 channel = i;
671                 prio_low = vchannel[i].priority;
672             }
673         }
674         if(prio_low > priority)
675         {
676             return -1;
677         }
678     }
679 
680     if(lvolume < 0)
681     {
682         lvolume = 0;
683     }
684     if(rvolume < 0)
685     {
686         rvolume = 0;
687     }
688     if(lvolume > MAXVOLUME)
689     {
690         lvolume = MAXVOLUME;
691     }
692     if(rvolume > MAXVOLUME)
693     {
694         rvolume = MAXVOLUME;
695     }
696 
697     vchannel[channel].samplenum = samplenum;
698     // Prevent samples from being played at EXACT same point
699     vchannel[channel].fp_samplepos = INT_TO_FIX((channel * 4) % soundcache[samplenum].sample.soundlen);
700     vchannel[channel].fp_period = (INT_TO_FIX(1) * speed / 100) * soundcache[samplenum].sample.frequency / playfrequency;
701     vchannel[channel].volume[0] = lvolume;
702     vchannel[channel].volume[1] = rvolume;
703     vchannel[channel].priority = priority;
704     vchannel[channel].channels = soundcache[samplenum].sample.channels;
705     vchannel[channel].active = CHANNEL_PLAYING;
706     vchannel[channel].paused = 0;
707     vchannel[channel].playid = ++sample_play_id;
708 
709     return channel;
710 }
711 
sound_loop_sample(int samplenum,unsigned int priority,int lvolume,int rvolume,unsigned int speed)712 int sound_loop_sample(int samplenum, unsigned int priority, int lvolume, int rvolume, unsigned int speed)
713 {
714     int ch = sound_play_sample(samplenum, priority, lvolume, rvolume, speed);
715     if(ch >= 0)
716     {
717         vchannel[ch].active = CHANNEL_LOOPING;
718     }
719     return ch;
720 }
721 
sound_query_channel(int playid)722 int sound_query_channel(int playid)
723 {
724     int i;
725     for(i = 0; i < max_channels; i++)
726     {
727         if(vchannel[i].playid == playid && vchannel[i].active)
728         {
729             return i;
730         }
731     }
732     return -1;
733 }
734 
sound_id(int channel)735 int sound_id(int channel)
736 {
737     if(vchannel[channel].active) return vchannel[channel].playid;
738     else return -1;
739 }
740 
sound_is_active(int channel)741 int sound_is_active(int channel)
742 {
743     if( vchannel[channel].active ) return 1;
744     return 0;
745 }
746 
sound_stop_sample(int channel)747 void sound_stop_sample(int channel)
748 {
749     if(channel < 0 || channel >= max_channels)
750     {
751         return;
752     }
753     vchannel[channel].active = 0;
754 }
755 
sound_stopall_sample()756 void sound_stopall_sample()
757 {
758     int channel;
759     for(channel = 0; channel < max_channels; channel++)
760     {
761         vchannel[channel].active = 0;
762     }
763 }
764 
sound_pause_sample(int toggle)765 void sound_pause_sample(int toggle)
766 {
767     int channel;
768     for(channel = 0; channel < max_channels; channel++)
769     {
770         vchannel[channel].paused = toggle;
771     }
772 }
773 
sound_pause_single_sample(int toggle,int channel)774 void sound_pause_single_sample(int toggle, int channel)
775 {
776     vchannel[channel].paused = toggle;
777 }
778 
sound_volume_sample(int channel,int lvolume,int rvolume)779 void sound_volume_sample(int channel, int lvolume, int rvolume)
780 {
781     if(channel < 0 || channel >= max_channels)
782     {
783         return;
784     }
785     if(lvolume < 0)
786     {
787         lvolume = 0;
788     }
789     if(rvolume < 0)
790     {
791         rvolume = 0;
792     }
793     if(lvolume > MAXVOLUME)
794     {
795         lvolume = MAXVOLUME;
796     }
797     if(rvolume > MAXVOLUME)
798     {
799         rvolume = MAXVOLUME;
800     }
801     vchannel[channel].volume[0] = lvolume;
802     vchannel[channel].volume[1] = rvolume;
803 }
804 
sound_getpos_sample(int channel)805 int sound_getpos_sample(int channel)
806 {
807     if(channel < 0 || channel >= max_channels)
808     {
809         return 0;
810     }
811     return FIX_TO_INT(vchannel[channel].fp_samplepos);
812 }
813 
814 //////////////////////////////// ADPCM music ////////////////////////////////
815 
816 static int adpcm_handle = -1;
817 static unsigned char *adpcm_inbuf;
818 static int music_looping = 0;
819 static int music_atend = 0;
820 #define	BOR_MUSIC_VERSION_MONO   0x00010000
821 #define	BOR_MUSIC_VERSION_STEREO 0x00010001
822 #define	BOR_IDENTIFIER "BOR music"
823 
824 #ifndef DC
825 #pragma pack (1)
826 #endif
827 
828 typedef struct
829 {
830     char	identifier[16];
831     char	artist[64];
832     char	title[64];
833     unsigned int	version;
834     int		frequency;
835     int		channels;
836     int		datastart;
837 } bor_header;
838 
839 #ifndef DC
840 #pragma pack (4)
841 #endif
842 
843 static bor_header borhead;
844 static short loop_valprev[2];
845 static char loop_index[2];
846 static int loop_state_set;
847 static u32 loop_offset;
848 
sound_close_adpcm()849 void sound_close_adpcm()
850 {
851 
852     int i;
853 
854     // Prevent any further access by the ISR
855     musicchannel.active = 0;
856     for(i = 0; i < MUSIC_NUM_BUFFERS; i++)
857     {
858         musicchannel.fp_playto[i] = 0;
859     }
860 
861     // Close file...
862     if(adpcm_handle >= 0)
863     {
864         closepackfile(adpcm_handle);
865     }
866     adpcm_handle = -1;
867 
868     if(adpcm_inbuf != NULL)
869     {
870         free(adpcm_inbuf);
871         adpcm_inbuf = NULL;
872     }
873 
874     for(i = 0; i < MUSIC_NUM_BUFFERS; i++)
875     {
876         if(musicchannel.buf[i] != NULL)
877         {
878             free(musicchannel.buf[i]);
879             musicchannel.buf[i] = NULL;
880         }
881     }
882 
883     memset(&musicchannel, 0, sizeof(musicchannelstruct));
884     memset(&borhead, 0, sizeof(bor_header));
885 
886     adpcm_reset();
887     loop_valprev[0] = loop_valprev[1] = 0;
888     loop_index[0] = loop_index[1] = 0;
889     loop_state_set = 0;
890 }
891 
sound_open_adpcm(char * filename,char * packname,int volume,int loop,u32 music_offset)892 int sound_open_adpcm(char *filename, char *packname, int volume, int loop, u32 music_offset)
893 {
894 
895     int i;
896 
897     if(!mixing_inited)
898     {
899         return 0;
900     }
901     if(!mixing_active)
902     {
903         return 0;
904     }
905 
906     sound_close_music();
907 
908     // Open file, etcetera
909     adpcm_handle = openpackfile(filename, packname);
910     if(adpcm_handle < 0)
911     {
912         return 0;
913     }
914 
915     // Read header
916     if(readpackfile(adpcm_handle, &borhead, sizeof(bor_header)) != sizeof(bor_header))
917     {
918         goto error_exit;
919     }
920 
921     borhead.version = SwapLSB32(borhead.version);
922     borhead.frequency = SwapLSB32(borhead.frequency);
923     borhead.channels = SwapLSB32(borhead.channels);
924     borhead.datastart = SwapLSB32(borhead.datastart);
925 
926     // Is it really a BOR music file?
927     if(strncmp(borhead.identifier, BOR_IDENTIFIER, 16) != 0)
928     {
929         goto error_exit;
930     }
931 
932     // Can I play it?
933     if((borhead.version != BOR_MUSIC_VERSION_MONO && borhead.version != BOR_MUSIC_VERSION_STEREO) ||
934             (borhead.channels != 1 && borhead.channels != 2) ||
935             borhead.frequency < 11025 || borhead.frequency > 44100)
936     {
937         goto error_exit;
938     }
939     // Seek to beginning of data
940     if(seekpackfile(adpcm_handle, borhead.datastart, SEEK_SET) != borhead.datastart)
941     {
942         goto error_exit;
943     }
944 
945     memset(&musicchannel, 0, sizeof(musicchannelstruct));
946 
947     musicchannel.fp_period = INT_TO_FIX(borhead.frequency) / playfrequency;
948     musicchannel.volume[0] = volume;
949     musicchannel.volume[1] = volume;
950     musicchannel.channels = borhead.channels;
951     music_looping = loop;
952     music_atend = 0;
953 
954     adpcm_inbuf = malloc(MUSIC_BUF_SIZE / 2);
955     if(adpcm_inbuf == NULL)
956     {
957         goto error_exit;
958     }
959 
960     for(i = 0; i < MUSIC_NUM_BUFFERS; i++)
961     {
962         musicchannel.buf[i] = malloc(MUSIC_BUF_SIZE * sizeof(short));
963         if(musicchannel.buf[i] == NULL)
964         {
965             goto error_exit;
966         }
967         memset(musicchannel.buf[i], 0, MUSIC_BUF_SIZE * sizeof(short));
968     }
969 
970     loop_offset = music_offset;
971     music_type = 0;
972 
973     return 1;
974 error_exit:
975     sound_close_music();
976     closepackfile(adpcm_handle);
977     return 0;
978 }
979 
sound_update_adpcm()980 void sound_update_adpcm()
981 {
982 
983     int samples, readsamples, samples_to_read;
984     short *outptr;
985     int i, j;
986 
987     if((adpcm_handle < 0) || (music_type != 0))
988     {
989         return;
990     }
991     if(!mixing_inited || !mixing_active)
992     {
993         sound_close_music();
994         return;
995     }
996     if(musicchannel.paused)
997     {
998         return;
999     }
1000 
1001 
1002     // Just to be sure: check if all goes well...
1003     for(i = 0; i < MUSIC_NUM_BUFFERS; i++)
1004     {
1005         if(musicchannel.fp_playto[i] > INT_TO_FIX(MUSIC_BUF_SIZE))
1006         {
1007             musicchannel.fp_playto[i] = 0;
1008             return;
1009         }
1010     }
1011 
1012 
1013     // Need to update?
1014     for(j = 0, i = musicchannel.playing_buffer + 1; j < MUSIC_NUM_BUFFERS; j++, i++)
1015     {
1016         i %= MUSIC_NUM_BUFFERS;
1017 
1018         if(musicchannel.fp_playto[i] == 0)
1019         {
1020             // Buffer needs to be filled
1021 
1022             samples = 0;
1023             outptr = musicchannel.buf[i];
1024 
1025             if(!music_looping)
1026             {
1027                 if(music_atend)
1028                 {
1029                     // Close file when done playing all buffers
1030                     if(!musicchannel.active)
1031                     {
1032                         sound_close_music();
1033                         return;
1034                     }
1035                 }
1036                 else
1037                 {
1038                     readsamples = readpackfile(adpcm_handle, adpcm_inbuf, MUSIC_BUF_SIZE / 2) * 2;
1039                     if(readsamples <= 0)
1040                     {
1041                         // EOF
1042                         music_atend = 1;
1043                         return;
1044                     }
1045                     // Play this bit
1046                     adpcm_decode(adpcm_inbuf, outptr, readsamples / 2, musicchannel.channels);
1047                     samples = readsamples;
1048                 }
1049             }
1050             else while(samples < MUSIC_BUF_SIZE)
1051                 {
1052                     samples_to_read = MUSIC_BUF_SIZE - samples;
1053                     if(!loop_state_set && seekpackfile(adpcm_handle, 0, SEEK_CUR) <= (borhead.datastart + loop_offset) && seekpackfile(adpcm_handle, 0, SEEK_CUR) > (borhead.datastart + loop_offset - samples_to_read / 2))
1054                     {
1055                         readsamples = readpackfile(adpcm_handle, adpcm_inbuf, borhead.datastart + loop_offset - seekpackfile(adpcm_handle, 0, SEEK_CUR)) * 2;
1056                         adpcm_decode(adpcm_inbuf, outptr, readsamples / 2, musicchannel.channels);
1057                         loop_valprev[0] = adpcm_valprev(0);
1058                         loop_index[0] = adpcm_index(0);
1059                         if(musicchannel.channels == SOUND_STEREO)
1060                         {
1061                             loop_valprev[1] = adpcm_valprev(1);
1062                             loop_index[1] = adpcm_index(1);
1063                         }
1064                         loop_state_set = 1;
1065                         outptr += readsamples;
1066                         samples += readsamples;
1067                     }
1068                     else
1069                     {
1070                         readsamples = readpackfile(adpcm_handle, adpcm_inbuf, samples_to_read / 2) * 2;
1071                         if(readsamples < 0)
1072                         {
1073                             // Error
1074                             sound_close_music();
1075                             return;
1076                         }
1077                         if(readsamples)
1078                         {
1079                             adpcm_decode(adpcm_inbuf, outptr, readsamples / 2, musicchannel.channels);
1080                             outptr += readsamples;
1081                             samples += readsamples;
1082                         }
1083                         if(readsamples < samples_to_read)
1084                         {
1085                             // At start of data already?
1086                             if(seekpackfile(adpcm_handle, 0, SEEK_CUR) == borhead.datastart)
1087                             {
1088                                 // Must be some error
1089                                 sound_close_music();
1090                                 return;
1091                             }
1092                             // Seek to beginning of data
1093                             if(seekpackfile(adpcm_handle, borhead.datastart + loop_offset, SEEK_SET) != borhead.datastart + loop_offset)
1094                             {
1095                                 sound_close_music();
1096                                 return;
1097                             }
1098                             // Reset decoder
1099                             adpcm_loop_reset(0, loop_valprev[0], loop_index[0]);
1100                             if(musicchannel.channels == SOUND_STEREO)
1101                             {
1102                                 adpcm_loop_reset(1, loop_valprev[1], loop_index[1]);
1103                             }
1104                         }
1105                     }
1106                 }
1107             // Activate
1108             musicchannel.fp_playto[i] = INT_TO_FIX(samples);
1109             if(!musicchannel.active)
1110             {
1111                 musicchannel.playing_buffer = i;
1112                 musicchannel.active = 1;
1113             }
1114         }
1115     }
1116 }
1117 
sound_adpcm_tempo(int music_tempo)1118 void sound_adpcm_tempo(int music_tempo)
1119 {
1120     musicchannel.fp_period = (INT_TO_FIX(1) * music_tempo / 100) * borhead.frequency / playfrequency;
1121 }
1122 
sound_query_adpcm(char * artist,char * title)1123 int sound_query_adpcm(char *artist, char *title)
1124 {
1125     if(adpcm_handle < 0)
1126     {
1127         return 0;
1128     }
1129     if(artist)
1130     {
1131         strcpy(artist, borhead.artist);
1132     }
1133     if(title)
1134     {
1135         strcpy(title, borhead.title);
1136     }
1137     return 1;
1138 }
1139 
1140 /////////////////////////// Ogg Vorbis decoding ///////////////////////////////
1141 // Plombo's Ogg Vorbis decoder for OpenBOR. Uses libvorbisfile or libvorbisidec.
1142 
1143 #if TREMOR || DC
1144 #define ov_decode(vf,buffer,length,bitstream) ov_read(vf,buffer,length,bitstream)
1145 #else
1146 #define ov_decode(vf,buffer,length,bitstream) ov_read(vf,buffer,length,0,2,1,bitstream)
1147 #endif
1148 
1149 OggVorbis_File *oggfile;
1150 vorbis_info *stream_info;
1151 int current_section, ogg_handle;
1152 
1153 // I/O functions used by libvorbisfile
readpackfile_callback(void * buf,size_t len,size_t nmembers,int * handle)1154 size_t readpackfile_callback(void *buf, size_t len, size_t nmembers, int *handle)
1155 {
1156     return readpackfile(*handle, buf, (int)(len * nmembers));
1157 }
closepackfile_callback(void * ptr)1158 int closepackfile_callback(void *ptr)
1159 {
1160 #ifdef VERBOSE
1161     printf ("closepack cb %d\n", *(int *)ptr);
1162 #endif
1163 
1164     return closepackfile(*(int *)ptr);
1165 }
seekpackfile_callback(int * handle,ogg_int64_t offset,int whence)1166 int seekpackfile_callback(int *handle, ogg_int64_t offset, int whence)
1167 {
1168     return seekpackfile(*handle, (int)offset, whence);
1169 }
tellpackfile_callback(int * handle)1170 int tellpackfile_callback(int *handle)
1171 {
1172     return seekpackfile(*handle, 0, SEEK_CUR);
1173 }
1174 
sound_close_ogg()1175 void sound_close_ogg()
1176 {
1177     int i;
1178 
1179     ov_clear(oggfile);
1180     free(oggfile);
1181     oggfile = NULL;
1182     music_type = -1;
1183 
1184     for(i = 0; i < MUSIC_NUM_BUFFERS; i++)
1185     {
1186         if(musicchannel.buf[i] != NULL)
1187         {
1188             free(musicchannel.buf[i]);
1189             musicchannel.buf[i] = NULL;
1190         }
1191     }
1192 
1193     memset(&musicchannel, 0, sizeof(musicchannelstruct));
1194 }
1195 
sound_open_ogg(char * filename,char * packname,int volume,int loop,u32 music_offset)1196 int sound_open_ogg(char *filename, char *packname, int volume, int loop, u32 music_offset)
1197 {
1198 
1199     int i;
1200 
1201     static ov_callbacks ogg_callbacks =
1202     {
1203         (size_t ( *)(void *, size_t, size_t, void *))  readpackfile_callback,
1204         (int ( *)(void *, ogg_int64_t, int))           seekpackfile_callback,
1205         (int ( *)(void *))                             closepackfile_callback,
1206         (long ( *)(void *))                            tellpackfile_callback
1207     };
1208 
1209     if(!mixing_inited)
1210     {
1211         return 0;
1212     }
1213     if(!mixing_active)
1214     {
1215         return 0;
1216     }
1217 
1218     sound_close_music();
1219 #ifdef VERBOSE
1220     printf("trying to open OGG file %s from %s, vol %d, loop %d, ofs %u\n", filename, packname, volume, loop, music_offset);
1221 #endif
1222     // Open file, etcetera
1223     ogg_handle = openpackfile(filename, packname);
1224 #ifdef VERBOSE
1225     printf ("ogg handle %d\n", ogg_handle);
1226 #endif
1227     if(ogg_handle < 0)
1228     {
1229 #ifdef VERBOSE
1230         printf("couldn't get handle\n");
1231 #endif
1232         return 0;
1233     }
1234     oggfile = malloc(sizeof(OggVorbis_File));
1235     if (ov_open_callbacks(&ogg_handle, oggfile, NULL, 0, ogg_callbacks) != 0)
1236     {
1237 #ifdef VERBOSE
1238         printf("ov_open_callbacks failed\n");
1239 #endif
1240         goto error_exit;
1241     }
1242     // Can I play it?
1243     stream_info = ov_info(oggfile, -1);
1244     if((stream_info->channels != 1 && stream_info->channels != 2) ||
1245             stream_info->rate < 11025 || stream_info->rate > 44100)
1246     {
1247         sound_close_ogg();
1248 #ifdef VERBOSE
1249         printf("NOT can i play it\n");
1250 #endif
1251 
1252         goto error_exit;
1253     }
1254 
1255     memset(&musicchannel, 0, sizeof(musicchannelstruct));
1256 
1257     musicchannel.fp_period = INT_TO_FIX(stream_info->rate) / playfrequency;
1258     musicchannel.volume[0] = volume;
1259     musicchannel.volume[1] = volume;
1260     musicchannel.channels = stream_info->channels;
1261     music_looping = loop;
1262     music_atend = 0;
1263 
1264     for(i = 0; i < MUSIC_NUM_BUFFERS; i++)
1265     {
1266         musicchannel.buf[i] = malloc(MUSIC_BUF_SIZE * sizeof(short));
1267         if(musicchannel.buf[i] == NULL)
1268         {
1269             sound_close_ogg();
1270 #ifdef VERBOSE
1271             printf("buf is null\n");
1272 #endif
1273             goto error_exit;
1274         }
1275         memset(musicchannel.buf[i], 0, MUSIC_BUF_SIZE * sizeof(short));
1276     }
1277 
1278     loop_offset = music_offset;
1279     music_type = 1;
1280 
1281 #ifdef VERBOSE
1282     printf("ogg is opened\n");
1283 #endif
1284     return 1;
1285 
1286 error_exit:
1287     closepackfile(ogg_handle);
1288     return 0;
1289 
1290 }
1291 
sound_update_ogg()1292 void sound_update_ogg()
1293 {
1294 
1295     int samples, readsamples, samples_to_read;
1296     short *outptr;
1297     int i, j;
1298 
1299     if(!mixing_inited || !mixing_active)
1300     {
1301         sound_close_music();
1302         return;
1303     }
1304     if(musicchannel.paused)
1305     {
1306         return;
1307     }
1308 
1309     // Just to be sure: check if all goes well...
1310     for(i = 0; i < MUSIC_NUM_BUFFERS; i++)
1311     {
1312         if(musicchannel.fp_playto[i] > INT_TO_FIX(MUSIC_BUF_SIZE))
1313         {
1314             musicchannel.fp_playto[i] = 0;
1315             return;
1316         }
1317     }
1318 
1319 
1320     // Need to update?
1321     for(j = 0, i = musicchannel.playing_buffer + 1; j < MUSIC_NUM_BUFFERS; j++, i++)
1322     {
1323         i %= MUSIC_NUM_BUFFERS;
1324 
1325         if(musicchannel.fp_playto[i] == 0)
1326         {
1327             // Buffer needs to be filled
1328 
1329             samples = 0;
1330             outptr = musicchannel.buf[i];
1331 
1332             if(!music_looping)
1333             {
1334                 if(music_atend)
1335                 {
1336                     // Close file when done playing all buffers
1337                     if(!musicchannel.active)
1338                     {
1339                         sound_close_music();
1340                         return;
1341                     }
1342                 }
1343                 else while(samples < MUSIC_BUF_SIZE)
1344                     {
1345                         readsamples = ov_decode(oggfile, (char *)outptr, 2 * (MUSIC_BUF_SIZE - samples), &current_section) / 2;
1346                         if (readsamples == 0)
1347                         {
1348                             music_atend = 1;
1349                             return;
1350                         }
1351                         else if (readsamples < 0)
1352                         {
1353                             sound_close_music();
1354                             return;
1355                         }
1356                         outptr += readsamples;
1357                         samples += readsamples;
1358                     }
1359             }
1360             else while(samples < MUSIC_BUF_SIZE)
1361                 {
1362                     samples_to_read = MUSIC_BUF_SIZE - samples;
1363                     readsamples = ov_decode(oggfile, (char *)outptr, 2 * samples_to_read, &current_section) / 2;
1364                     if(readsamples < 0)
1365                     {
1366                         // Error
1367                         sound_close_music();
1368                         return;
1369                     }
1370                     else if(readsamples > 0)
1371                     {
1372                         outptr += readsamples;
1373                         samples += readsamples;
1374                     }
1375                     else if(readsamples < samples_to_read)
1376                     {
1377                         // At start of data already?
1378                         if(ov_pcm_tell(oggfile) == 0)
1379                         {
1380                             // Must be some error
1381                             sound_close_music();
1382                             return;
1383                         }
1384                         // Seek to beginning of data
1385                         if(ov_pcm_seek(oggfile, loop_offset) != 0)
1386                         {
1387                             sound_close_music();
1388                             return;
1389                         }
1390                     }
1391                 }
1392             // Activate
1393             musicchannel.fp_playto[i] = INT_TO_FIX(samples);
1394             if(!musicchannel.active)
1395             {
1396                 musicchannel.playing_buffer = i;
1397                 musicchannel.active = 1;
1398             }
1399         }
1400     }
1401 }
1402 
sound_ogg_tempo(int music_tempo)1403 void sound_ogg_tempo(int music_tempo)
1404 {
1405     musicchannel.fp_period = (INT_TO_FIX(1) * music_tempo / 100) * stream_info->rate / playfrequency;
1406 }
1407 
sound_query_ogg(char * artist,char * title)1408 int sound_query_ogg(char *artist, char *title)
1409 {
1410     int i;
1411     char *current;
1412     vorbis_comment *comment = ov_comment(oggfile, -1);
1413 
1414     if (!artist || !title)
1415     {
1416         return 1;
1417     }
1418 
1419     for(i = 0; i < comment->comments; i++)
1420     {
1421         current = comment->user_comments[i];
1422         if (strncmp("ARTIST=", current, 7) == 0)
1423         {
1424             strcpy(artist, current + 7);
1425         }
1426         else if (strncmp("TITLE=", current, 6) == 0)
1427         {
1428             strcpy(title, current + 6);
1429         }
1430     }
1431 
1432     return 1;
1433 }
1434 
1435 /////////////////////////////// INIT / EXIT //////////////////////////////////
1436 
sound_open_music(char * filename,char * packname,int volume,int loop,u32 music_offset)1437 int sound_open_music(char *filename, char *packname, int volume, int loop, u32 music_offset)
1438 {
1439     static char fnam[128];
1440 #ifdef VERBOSE
1441     printf("trying to open music file %s from %s, vol %d, loop %d, ofs %u\n", filename, packname, volume, loop, music_offset);
1442 #endif
1443     // try opening filename exactly as specified
1444     if(sound_open_adpcm(filename, packname, volume, loop, music_offset))
1445     {
1446         return 1;
1447     }
1448     if(sound_open_ogg(filename, packname, volume, loop, music_offset))
1449     {
1450         return 1;
1451     }
1452 
1453     // handle adding an extension to the filename
1454     sprintf(fnam, "%s.bor", filename);
1455     if(sound_open_adpcm(fnam, packname, volume, loop, music_offset))
1456     {
1457         return 1;
1458     }
1459     sprintf(fnam, "%s.ogg", filename);
1460     if(sound_open_ogg(fnam, packname, volume, loop, music_offset))
1461     {
1462         return 1;
1463     }
1464     sprintf(fnam, "%s.oga", filename);
1465     if(sound_open_ogg(fnam, packname, volume, loop, music_offset))
1466     {
1467         return 1;
1468     }
1469 
1470     return 0;
1471 }
1472 
sound_close_music()1473 void sound_close_music()
1474 {
1475     switch(music_type)
1476     {
1477     case 0:
1478         sound_close_adpcm();
1479         break;
1480     case 1:
1481         sound_close_ogg();
1482     }
1483     music_type = -1;
1484 }
1485 
sound_update_music()1486 void sound_update_music()
1487 {
1488     switch(music_type)
1489     {
1490     case 0:
1491         sound_update_adpcm();
1492         break;
1493     case 1:
1494         sound_update_ogg();
1495     }
1496 }
1497 
sound_query_music(char * artist,char * title)1498 int sound_query_music(char *artist, char *title)
1499 {
1500     switch(music_type)
1501     {
1502     case 0:
1503         return sound_query_adpcm(artist, title);
1504     case 1:
1505         return sound_query_ogg(artist, title);
1506     default:
1507         return 0;
1508     }
1509 }
1510 
sound_music_tempo(int music_tempo)1511 void sound_music_tempo(int music_tempo)
1512 {
1513 
1514     switch(music_type)
1515     {
1516     case 0:
1517         sound_adpcm_tempo(music_tempo);
1518         break;
1519     case 1:
1520         sound_ogg_tempo(music_tempo);
1521     }
1522 }
1523 
sound_volume_music(int left,int right)1524 void sound_volume_music(int left, int right)
1525 {
1526     if(left < 0)
1527     {
1528         left = 0;
1529     }
1530     if(right < 0)
1531     {
1532         right = 0;
1533     }
1534     if(left > MAXVOLUME * 8)
1535     {
1536         left = MAXVOLUME * 8;
1537     }
1538     if(right > MAXVOLUME * 8)
1539     {
1540         right = MAXVOLUME * 8;
1541     }
1542     musicchannel.volume[0] = left;
1543     musicchannel.volume[1] = right;
1544 }
1545 
sound_pause_music(int toggle)1546 void sound_pause_music(int toggle)
1547 {
1548     musicchannel.paused = toggle;
1549 }
1550 
sound_stop_playback()1551 void sound_stop_playback()
1552 {
1553     int i;
1554     if(!mixing_inited)
1555     {
1556         return;
1557     }
1558     if(!mixing_active)
1559     {
1560         return;
1561     }
1562     sound_close_music();
1563     for(i = 0; i < max_channels; i++)
1564     {
1565         sound_stop_sample(i);
1566     }
1567     SB_playstop();
1568     mixing_active = 0;
1569 }
1570 
sound_start_playback(int bits,int frequency)1571 int sound_start_playback(int bits, int frequency)
1572 {
1573     int i;
1574 
1575     if(!mixing_inited)
1576     {
1577         return 0;
1578     }
1579 
1580     sound_stop_playback();
1581 
1582     if(bits != 8 && bits != 16)
1583     {
1584         return 0;
1585     }
1586 
1587 #if WIN || LINUX || DARWIN || SYMBIAN
1588     //
1589 #else
1590     // Most consoles support natively 16/44100
1591     bits = 16;
1592     frequency = 44100;
1593 #endif
1594 
1595     playbits = bits;
1596     playfrequency = frequency;
1597 
1598     for(i = 0; i < max_channels; i++)
1599     {
1600         sound_stop_sample(i);
1601     }
1602     SB_playstop();
1603     if(!SB_playstart(playbits, playfrequency))
1604     {
1605         return 0;
1606     }
1607 
1608     mixing_active = 1;
1609     samplesplayed = 0;
1610     return 1;
1611 }
1612 
1613 // Stop everything and free used memory
sound_exit()1614 void sound_exit()
1615 {
1616 
1617     sound_stop_playback();
1618     sound_unload_all_samples();
1619 
1620     if(mixbuf != NULL)
1621     {
1622         free(mixbuf);
1623         mixbuf = NULL;
1624     }
1625 
1626 #ifdef PSP
1627     SB_exit();
1628 #endif
1629 
1630     mixing_inited = 0;
1631 }
1632 
1633 // Find and initialize SoundBlaster, allocate memory, initialize tables...
sound_init(int channels)1634 int sound_init(int channels)
1635 {
1636     int i;
1637 
1638     if(channels < 2)
1639     {
1640         channels = 2;
1641     }
1642     if(channels > MAX_CHANNELS)
1643     {
1644         channels = MAX_CHANNELS;
1645     }
1646     sound_exit();
1647 
1648     // Allocate the maximum amount ever possibly needed for mixing
1649     if((mixbuf = malloc(MIXBUF_SIZE)) == NULL)
1650     {
1651 
1652 #ifdef PSP
1653         SB_exit();
1654 #endif
1655         return 0;
1656     }
1657 
1658     max_channels = channels;
1659     for(i = 0; i < max_channels; i++)
1660     {
1661         memset(&vchannel[i], 0, sizeof(channelstruct));
1662     }
1663 
1664     mixing_active = 0;
1665     mixing_inited = 1;
1666     List_Init(&samplelist);
1667 
1668     return 1;
1669 }
1670 
1671 // Returns time passed in milliseconds (since last call or start of playback),
1672 // or 0xFFFFFFFF if not available. This function is useful when synchronizing
1673 // stuff to sound.
sound_getinterval()1674 u32 sound_getinterval()
1675 {
1676     u32 msecs;
1677 
1678     if(!mixing_active)
1679     {
1680         return 0xFFFFFFFF;
1681     }
1682 
1683     msecs = 1000 * samplesplayed / playfrequency;
1684     samplesplayed -= msecs * playfrequency / 1000;
1685 
1686     return msecs;
1687 }
1688 
maxchannels()1689 int maxchannels()
1690 {
1691     return MAX_CHANNELS;
1692 }
1693 
1694