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), ¤t_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, ¤t_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