1 /*
2  * OpenBOR - http://www.LavaLit.com
3  * -----------------------------------------------------------------------
4  * All rights reserved, see LICENSE in OpenBOR root for details.
5  *
6  * Copyright (c) 2004 - 2011 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 <string.h>
38 #include <assert.h>
39 #include "utils.h"
40 #include "stristr.h"
41 #include "adpcm.h"
42 #include "borendian.h"
43 #include "sblaster.h"
44 #include "soundmix.h"
45 #include "packfile.h"
46 
47 #ifdef DC
48 #include <ivorbisfile.h>
49 #elif TREMOR
50 #include <tremor/ivorbisfile.h>
51 #else
52 #include <vorbis/vorbisfile.h>
53 #endif
54 
55 #if LINUX || GP2X || DINGOO || SYMBIAN
56 #define stricmp strcasecmp
57 #endif
58 
59 #define		AUDIOCIDE_VERSION	"2.00"
60 #define		MIXSHIFT		     3	    // 2 should be OK
61 #define		MAXVOLUME		     64	    // 64 for backw. compat.
62 #define		MAX_SAMPLES		     1024	// Should be well enough
63 #define		MAX_CHANNELS	     64	    // Should be well enough
64 
65 // Hardware settings for SoundBlaster (change only if latency is too big)
66 #define		SB_BUFFER_SIZE		 0x8000
67 #define		SB_BUFFER_SIZE_MASK	 0x7FFF
68 #define		SB_WBUFFER_SIZE		 0x4000
69 #define		SB_WBUFFER_SIZE_MASK 0x3FFF
70 #define		MIXBUF_SIZE		     SB_BUFFER_SIZE*8
71 #define		PREMIX_SIZE		     1024
72 #define		MIX_BLOCK_SIZE		 32
73 
74 // 20:12 fixed-point conversion macros.
75 // The maximum size of a sound is linked directly
76 // to the range of the fixed-point variables!
77 #define		INT_TO_FIX(i)		((unsigned int)i<<12)
78 #define		FIX_TO_INT(f)		((unsigned int)f>>12)
79 #define		MAX_SOUND_LEN		0xFFFFF
80 #define		CHANNEL_PLAYING		1
81 #define		CHANNEL_LOOPING		2
82 #define		MUSIC_NUM_BUFFERS	4
83 #define		MUSIC_BUF_SIZE		(16*1024)	// In samples
84 #define		SOUND_MONO			1
85 #define		SOUND_STEREO		2
86 
87 #ifndef DC
88 #pragma pack(4)
89 #endif
90 
91 typedef struct{
92 	int           index;
93 	char		  *filename;
94 }s_soundcache;
95 s_soundcache soundcache[MAX_SAMPLES];
96 
97 typedef struct{
98 	int            active;		 // 1 = play, 2 = loop
99 	int				paused;
100 	int            samplenum;	 // Index of sound playing
101 	unsigned int   priority;	 // Used for SFX
102 	int            volume[2];	 // Stereo :)
103 	int            channels;
104 	unsigned int   fp_samplepos; // Position (fixed-point)
105 	unsigned int   fp_period;	 // Period (fixed-point)
106 }channelstruct;
107 
108 typedef struct{
109 	void *		   sampleptr;
110 	int			   soundlen;	 // Length in samples
111 	int            bits;		 // 8/16 bit
112 	int            frequency;    // 11025 * 1,2,4
113 	int            channels;
114 }samplestruct;
115 
116 typedef struct{
117 	int            active;
118 	int            paused;
119 	short *		   buf[MUSIC_NUM_BUFFERS];
120 	unsigned int   fp_playto[MUSIC_NUM_BUFFERS];
121 	unsigned int   fp_samplepos;  // Position (fixed-point)
122 	unsigned int   fp_period;	  // Period (fixed-point)
123 	int			   playing_buffer;
124 	int            volume[2];
125 	int            channels;
126 }musicchannelstruct;
127 
128 static channelstruct vchannel[MAX_CHANNELS];
129 static musicchannelstruct musicchannel;
130 static samplestruct sampledata[MAX_SAMPLES];
131 static s32 *mixbuf = NULL;
132 static int playbits;
133 static int playfrequency;
134 static int max_channels = 0;
135 
136 #ifdef XBOX
137 static char *DMAbuf8 = NULL;
138 static u16 *DMAbuf16 = NULL;
139 #endif
140 
141 // Global shifter for hardware frequency adjustment (applied to periods)
142 static u32 hard_shift;
143 
144 // Indicates whether the hardware is playing, and if mixing is active
145 static int mixing_active = 0;
146 
147 // Indicates whether the sound system is initialized
148 static int mixing_inited = 0;
149 
150 // Counts the total number of samples played
151 static u32 samplesplayed;
152 
153 // Records type of currently playing music: 0=ADPCM, 1=Vorbis
154 static int music_type = 0;
155 
156 //////////////////////////////// WAVE LOADER //////////////////////////////////
157 
158 #ifndef DC
159 #ifdef SDL
160 #pragma pack(push, r1, 16)
161 #else
162 #pragma pack(push)
163 #endif
164 #pragma pack(1)
165 #endif
166 
167 
168 #define		HEX_RIFF	0x46464952
169 #define		HEX_WAVE	0x45564157
170 #define		HEX_fmt		0x20746D66
171 #define		HEX_data	0x61746164
172 #define		FMT_PCM		0x0001
173 
loadwave(char * filename,char * packname,samplestruct * buf,unsigned int maxsize)174 static int loadwave(char *filename, char *packname, samplestruct *buf, unsigned int maxsize){
175 	struct{
176 		u32				riff;
177 		u32				size;
178 		u32				type;
179 	}riffheader;
180 	struct{
181 		u32				tag;
182 		u32				size;
183 	}rifftag;
184 	struct{
185 		u16				format;		// 1 = PCM
186 		u16				channels;	// Mono, stereo
187 		u32				samplerate;	// 11025, 22050, 44100
188 		u32				bps;		// Bytes/second
189 		u16				unknown;
190 		u16				samplebits;	// 8, 12, 16
191 	}fmt;
192 
193 	int handle;
194 	int mulbytes;
195 
196 
197 	if(buf==NULL) return 0;
198 
199 	if((handle=openpackfile(filename, packname))==-1) return 0;
200 	if(readpackfile(handle, &riffheader, sizeof(riffheader)) != sizeof(riffheader)){
201 		closepackfile(handle);
202 		return 0;
203 	}
204 
205 	riffheader.riff = SwapLSB32(riffheader.riff);
206 	riffheader.size = SwapLSB32(riffheader.size);
207 	riffheader.type = SwapLSB32(riffheader.type);
208 
209 	if(riffheader.riff!=HEX_RIFF || riffheader.type!=HEX_WAVE){
210 		closepackfile(handle);
211 		return 0;
212 	}
213 
214 	rifftag.tag = 0;
215 	// Search for format tag
216 	while(rifftag.tag!=HEX_fmt){
217 		if(readpackfile(handle, &rifftag, sizeof(rifftag))!=sizeof(rifftag)){
218 			closepackfile(handle);
219 			return 0;
220 		}
221 		rifftag.tag = SwapLSB32(rifftag.tag);
222 		rifftag.size = SwapLSB32(rifftag.size);
223 		if(rifftag.tag!=HEX_fmt) seekpackfile(handle,rifftag.size,SEEK_CUR);
224 	}
225 	if(readpackfile(handle, &fmt, sizeof(fmt))!=sizeof(fmt)){
226 		closepackfile(handle);
227 		return 0;
228 	}
229 
230 	fmt.format = SwapLSB16(fmt.format);
231 	fmt.channels = SwapLSB16(fmt.channels);
232 	fmt.unknown = SwapLSB16(fmt.unknown);
233 	fmt.samplebits = SwapLSB16(fmt.samplebits);
234 	fmt.samplerate = SwapLSB32(fmt.samplerate);
235 	fmt.bps = SwapLSB32(fmt.bps);
236 
237 	if(rifftag.size>sizeof(fmt)) seekpackfile(handle,rifftag.size-sizeof(fmt),SEEK_CUR);
238 
239 	if(fmt.format!=FMT_PCM || (fmt.channels!=1 && fmt.channels!=2) || (fmt.samplebits!=8 && fmt.samplebits!=16)){
240 		closepackfile(handle);
241 		return 0;
242 	}
243 	mulbytes = (fmt.samplebits==16 ? 2 : 1);
244 
245 
246 	// Search for data tag
247 	while(rifftag.tag!=HEX_data){
248 		if(readpackfile(handle, &rifftag, sizeof(rifftag))!=sizeof(rifftag)){
249 			closepackfile(handle);
250 			return 0;
251 		}
252 		rifftag.tag = SwapLSB32(rifftag.tag);
253 		rifftag.size = SwapLSB32(rifftag.size);
254 		if(rifftag.tag!=HEX_data) seekpackfile(handle,rifftag.size,SEEK_CUR);
255 	}
256 
257 	if(rifftag.size<maxsize) maxsize = rifftag.size;
258 	if((buf->sampleptr = malloc(maxsize*mulbytes+8))==NULL){
259 		closepackfile(handle);
260 		return 0;
261 	}
262 	if(fmt.samplebits==8) memset(buf->sampleptr, 0x80, maxsize*mulbytes+8);
263 	else memset(buf->sampleptr, 0, maxsize*mulbytes+8);
264 
265 	if(readpackfile(handle, buf->sampleptr, maxsize*mulbytes) != (int)maxsize*mulbytes){
266 		if(buf->sampleptr != NULL){
267 			free(buf->sampleptr);
268 			buf->sampleptr = NULL;
269 		}
270 		closepackfile(handle);
271 		return 0;
272 	}
273 
274 	closepackfile(handle);
275 
276 	buf->soundlen = maxsize;
277 	buf->bits = fmt.samplebits;
278 	buf->frequency = fmt.samplerate;
279 	buf->channels = fmt.channels;
280 
281 	return maxsize;
282 }
283 
sound_free_sample(int which)284 void sound_free_sample(int which){
285 	if(!mixing_inited) return;
286 	if(which<0 || which>=MAX_SAMPLES) return;
287 	if(sampledata[which].sampleptr != NULL){
288 		free(sampledata[which].sampleptr);
289 		sampledata[which].sampleptr = NULL;
290 		memset(&sampledata[which], 0, sizeof(samplestruct));
291 	}
292 }
293 
294 // Returns index of sample, or -1 if not loaded
sound_alloc_sample(char * filename,char * packfilename)295 int sound_alloc_sample(char *filename, char *packfilename){
296 	int i;
297 	if(!mixing_inited) return -1;
298 	// Search for available slot to store sample data
299 	for(i=0; i<MAX_SAMPLES; i++) if(sampledata[i].sampleptr==NULL) break;
300 	if(i>=MAX_SAMPLES) return -1;
301 	memset(&sampledata[i], 0, sizeof(samplestruct));
302 	if(!loadwave(filename, packfilename, &sampledata[i], MAX_SOUND_LEN)) return -1;
303 	return i;
304 }
305 
306 // Load a sound or return index
sound_load_sample(char * filename,char * packfilename,int iLog)307 int sound_load_sample(char *filename, char *packfilename, int iLog){
308 	int i, len;
309 	for(i=0; i<=MAX_SAMPLES; i++){
310 		if(i == MAX_SAMPLES) return -1;
311 		if(soundcache[i].filename == NULL) break;
312 		if(stricmp(filename, soundcache[i].filename)==0) return soundcache[i].index;
313 	}
314 	soundcache[i].index = sound_alloc_sample(filename, packfilename);
315 	if(soundcache[i].index == -1){
316 		if(!iLog)
317 		{
318 			writeToLogFile("\nsound_load_sample: Failed to load: %s\n", filename);
319 		}
320 		return -1;
321 	}
322 	len = strlen(filename);
323 	soundcache[i].filename = malloc(len + 1);
324 	strcpy(soundcache[i].filename, filename);
325 	soundcache[i].filename[len] = 0;
326 	return soundcache[i].index;
327 }
328 
329 // Changed to conserve memory: added this function
sound_unload_sample(int index)330 void sound_unload_sample(int index){
331 	if(index<0 || index>=MAX_SAMPLES) return;
332 	if(soundcache[index].filename != NULL){
333 		soundcache[index].index = -1;
334 		free(soundcache[index].filename);
335 		soundcache[index].filename = NULL;
336 	}
337 	sound_free_sample(index);
338 }
339 
sound_unload_all_samples()340 void sound_unload_all_samples(){
341 	int i;
342 	for(i=0;i<MAX_SAMPLES;i++){
343 		sound_unload_sample(i);
344 	}
345 }
346 
347 #ifndef DC
348 #ifdef SDL
349 #pragma pack(pop, r1)
350 #else
351 #pragma pack(pop)
352 #endif
353 #endif
354 
355 /////////////////////////////// Mix to DMA //////////////////////////////////
356 // Mixbuffer / DMA buffer data handling
357 // Writes mixbuffer data (16-bit mixed in 32-bit array)
358 // to 8-bit or 16-bit DMA buffer.
359 
360 // Fill the mixbuffer with silence
clearmixbuffer(unsigned int * buf,int n)361 static void clearmixbuffer(unsigned int * buf, int n){
362 	while((--n)>=0){
363 		*buf = 0x8000<<MIXSHIFT;
364 		++buf;
365 	}
366 }
367 
368 #ifdef XBOX
mixtoDMAlow(unsigned int * mbuf,char * dbuf,int dmaoffs,int numbytes)369 static int mixtoDMAlow(unsigned int *mbuf, char *dbuf, int dmaoffs, int numbytes){
370 	static int u;
371 	while((--numbytes)>=0){
372 		dmaoffs &= SB_BUFFER_SIZE_MASK;
373 		u = *mbuf >> (MIXSHIFT+8);
374 		if(u<0) u = 0;
375 		else if(u>0xFF) u = 0xFF;
376 		dbuf[dmaoffs] = u;
377 		++mbuf;
378 		++dmaoffs;
379 	}
380 	dmaoffs &= SB_BUFFER_SIZE_MASK;
381 	return dmaoffs;
382 }
383 
384 
385 
mixtoDMAhigh(unsigned int * mbuf,unsigned short * dbuf,int dmaoffs,int numwords)386 static int mixtoDMAhigh(unsigned int *mbuf, unsigned short *dbuf, int dmaoffs, int numwords){
387 	static unsigned int u;
388 	while((--numwords)>=0){
389 		dmaoffs &= SB_WBUFFER_SIZE_MASK;
390 		//u = *mbuf ;
391 		u = *mbuf >> MIXSHIFT;
392 		if(u<0) u = 0;
393 		else if(u>0xFFFF) u = 0xFFFF;
394 		dbuf[dmaoffs] = u;
395 		++mbuf;
396 		++dmaoffs;
397 	}
398 	dmaoffs &= SB_WBUFFER_SIZE_MASK;
399 	return dmaoffs;
400 }
401 #endif
402 
403 
404 
405 /////////////////////////////////// Mixers ///////////////////////////////////
406 // Mixers: mix (16-bit) in the mixbuffer, then write to DMA memory (see above).
407 // The mixing code handles fixed-point conversion and looping.
408 
409 static int dmamixpos;
410 
411 // Input: number of input samples to mix
mixaudio(unsigned int todo)412 static void mixaudio(unsigned int todo){
413 
414 	static int i, chan, lvolume, rvolume, lmusic, rmusic;
415 	static unsigned int fp_pos, fp_period, fp_len, fp_playto;
416 	static int snum;
417 	static unsigned char *sptr8;
418 	static short *sptr16;
419 
420 	// First mix the music, if playing
421 	if(musicchannel.active && !musicchannel.paused){
422 
423 		sptr16 = musicchannel.buf[musicchannel.playing_buffer];
424 		fp_playto = musicchannel.fp_playto[musicchannel.playing_buffer];
425 		fp_pos = musicchannel.fp_samplepos;
426 		fp_period = musicchannel.fp_period;
427 		lvolume = musicchannel.volume[0];
428 		rvolume = musicchannel.volume[1];
429 
430 		// Mix it
431 		for(i=0; i<(int)todo;){
432 
433 			// Reached end of playable area,
434 			// switch buffers or stop
435 			if(fp_pos >= fp_playto){
436 				// Done playing this one
437 				musicchannel.fp_playto[musicchannel.playing_buffer] = 0;
438 				// Advance to next buffer
439 				musicchannel.playing_buffer++;
440 				musicchannel.playing_buffer %= MUSIC_NUM_BUFFERS;
441 				// Correct position in next buffer
442 				fp_pos = fp_pos - fp_playto;
443 				// Anything to play?
444 				if(fp_pos < musicchannel.fp_playto[musicchannel.playing_buffer]){
445 					// Yeah, switch!
446 					sptr16 = musicchannel.buf[musicchannel.playing_buffer];
447 					fp_playto = musicchannel.fp_playto[musicchannel.playing_buffer];
448 				}
449 				else{
450 					// Nothing more to do
451 					// Also disable this buffer, just incase
452 					musicchannel.fp_playto[musicchannel.playing_buffer] = 0;
453 					fp_pos = 0;
454 					musicchannel.active = 0;
455 					// End for
456 					break;
457 				}
458 			}
459 
460 			// Mix a sample
461 			lmusic = rmusic = sptr16[FIX_TO_INT(fp_pos)];
462 			lmusic = (lmusic * lvolume / MAXVOLUME);
463 			rmusic = (rmusic * rvolume / MAXVOLUME);
464 			mixbuf[i++] += lmusic;
465 			if(musicchannel.channels == SOUND_MONO){
466 				mixbuf[i++] += rmusic;
467 			}
468 			fp_pos += fp_period;
469 		}
470 		musicchannel.fp_samplepos = fp_pos;
471 	}
472 
473 
474 	for(chan=0; chan<max_channels; chan++){
475 		if(vchannel[chan].active && !vchannel[chan].paused){
476 			unsigned modlen;
477 			snum = vchannel[chan].samplenum;
478 			modlen = sampledata[snum].soundlen;
479 			fp_len = INT_TO_FIX(sampledata[snum].soundlen);
480 			fp_pos = vchannel[chan].fp_samplepos;
481 			fp_period = vchannel[chan].fp_period;
482 			lvolume = vchannel[chan].volume[0];
483 			rvolume = vchannel[chan].volume[1];
484 			if(fp_len < 1) fp_len = 1;
485 			if(modlen < 1) modlen = 1;
486 			if(sampledata[snum].bits==8){
487 				sptr8 = sampledata[snum].sampleptr;
488 				for(i=0; i<(int)todo;){
489 					lmusic = rmusic = sptr8[FIX_TO_INT(fp_pos)];
490 					mixbuf[i++] += ((lmusic<<8) * lvolume / MAXVOLUME) - 0x8000;
491 					if(vchannel[chan].channels == SOUND_MONO){
492 						mixbuf[i++] += ((rmusic<<8) * rvolume / MAXVOLUME) - 0x8000;
493 					}
494 					fp_pos += fp_period;
495 
496 					// Reached end of sample, stop or loop
497 					if(fp_pos >= fp_len){
498 						fp_pos %= fp_len; // = INT_TO_FIX(0);
499 						if(vchannel[chan].active!=CHANNEL_LOOPING){
500 							vchannel[chan].active = 0;
501 							break;
502 						}
503 					}
504 				}
505 			}
506 			else if(sampledata[snum].bits==16){
507 				sptr16 = sampledata[snum].sampleptr;
508 				for(i=0; i<(int)todo;){
509 					lmusic = rmusic = sptr16[FIX_TO_INT(fp_pos)];
510 					mixbuf[i++] += (lmusic * lvolume / MAXVOLUME);
511 					if(vchannel[chan].channels == SOUND_MONO){
512 						mixbuf[i++] += (rmusic * rvolume / MAXVOLUME);
513 					}
514 					fp_pos += fp_period;
515 
516 					// Reached end of sample, stop or loop
517 					if(fp_pos >= fp_len){
518 						fp_pos %= fp_len; // = INT_TO_FIX(0);
519 						if(vchannel[chan].active!=CHANNEL_LOOPING){
520 							vchannel[chan].active = 0;
521 							break;
522 						}
523 					}
524 				}
525 			}
526 			vchannel[chan].fp_samplepos = fp_pos;
527 		}
528 	}
529 }
530 
531 //////////////////////////////// ISR ///////////////////////////////////
532 // Called by Soundblaster ISR
533 
534 #ifdef XBOX
535 
get_mixingactive()536 int get_mixingactive(){
537 	return mixing_active ;
538 }
539 
updatemixing_xbox(unsigned int todo)540 unsigned char* updatemixing_xbox(unsigned int todo) {
541 	static int curdmapos;
542 	if (!mixing_active) return NULL;
543 	clearmixbuffer(mixbuf, todo);
544 	mixaudio(todo);
545 	samplesplayed += (todo >> 1);
546 	dmamixpos = mixtoDMAhigh(mixbuf, DMAbuf16, 0, todo);
547 	return (unsigned char*)DMAbuf16;
548 }
549 
550 #else
551 
update_sample(unsigned char * buf,int size)552 void update_sample(unsigned char *buf, int size) {
553 	int i,u,todo = size;
554 	if (playbits==16) {
555 		todo >>= 1;
556 	}
557 
558 	clearmixbuffer((unsigned int*)mixbuf, todo);
559 	mixaudio(todo);
560 	samplesplayed += (todo >> 1);
561 
562 	if (playbits==8) {
563 		unsigned char *dst = buf;
564 		for(i=0;i<todo;i++) {
565 			u = mixbuf[i] >> (MIXSHIFT + 8);
566 			if (u<0) u=0; else if (u>0xff) u = 0xff;
567 			dst[i] = u;
568 		}
569 	}
570 	else {
571 		unsigned short *dst = (unsigned short*)buf;
572 		for(i=0;i<todo;i++) {
573 			u = mixbuf[i] >> MIXSHIFT;
574 			if (u<0) u=0; else if (u>0xffff) u = 0xffff;
575 			u^=0x8000;
576 			dst[i] = u;
577 		}
578 	}
579 }
580 #endif
581 
582 ////////////////////////// Sound effects control /////////////////////////////
583 // Functions to start, stop, loop, etc.
584 
585 // Speed in percents of normal.
586 // 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)587 int sound_play_sample(int samplenum, unsigned int priority, int lvolume, int rvolume, unsigned int speed){
588 
589 	int i;
590 	unsigned int prio_low;
591 	int channel;
592 
593 	if(speed<1) speed = 100;
594 	if(!mixing_inited) return -1;
595 	if(samplenum<0 || samplenum>=MAX_SAMPLES) return -1;
596 	if(!sampledata[samplenum].sampleptr) return -1;
597 
598 	// Try to find unused SFX channel
599 	channel = -1;
600 	for(i=0; i<max_channels; i++){
601 		if(!vchannel[i].active) channel = i;
602 	}
603 
604 	if(channel==-1){
605 		// Find SFX channel with lowest current priority
606 		for(i=0, prio_low=0xFFFFFFFF; i<max_channels; i++){
607 			if(vchannel[i].priority < prio_low){
608 				channel = i;
609 				prio_low = vchannel[i].priority;
610 			}
611 		}
612 		if(prio_low > priority) return -1;
613 	}
614 
615 	if(lvolume<0) lvolume = 0;
616 	if(rvolume<0) rvolume = 0;
617 	if(lvolume>MAXVOLUME) lvolume = MAXVOLUME;
618 	if(rvolume>MAXVOLUME) rvolume = MAXVOLUME;
619 
620 	vchannel[channel].samplenum = samplenum;
621 	// Prevent samples from being played at EXACT same point
622 	vchannel[channel].fp_samplepos = INT_TO_FIX((channel*4)%sampledata[samplenum].soundlen);
623 	vchannel[channel].fp_period = (INT_TO_FIX(1) * speed / 100) * sampledata[samplenum].frequency / playfrequency;
624 	vchannel[channel].volume[0] = lvolume;
625 	vchannel[channel].volume[1] = rvolume;
626 	vchannel[channel].priority = priority;
627 	vchannel[channel].channels = sampledata[samplenum].channels;
628 	vchannel[channel].active = CHANNEL_PLAYING;
629 	vchannel[channel].paused = 0;
630 
631 	return channel;
632 }
633 
sound_loop_sample(int samplenum,unsigned int priority,int lvolume,int rvolume,unsigned int speed)634 int sound_loop_sample(int samplenum, unsigned int priority, int lvolume, int rvolume, unsigned int speed){
635 	int ch = sound_play_sample(samplenum, priority, lvolume, rvolume, speed);
636 	if(ch>=0) vchannel[ch].active = CHANNEL_LOOPING;
637 	return ch;
638 }
639 
sound_stop_sample(int channel)640 void sound_stop_sample(int channel){
641 	if(channel<0 || channel>=max_channels) return;
642 	vchannel[channel].active = 0;
643 }
644 
sound_stopall_sample()645 void sound_stopall_sample(){
646 	int channel;
647 	for(channel=0; channel<max_channels; channel++){
648 		vchannel[channel].active = 0;
649 	}
650 }
651 
sound_pause_sample(int toggle)652 void sound_pause_sample(int toggle){
653 	int channel;
654 	for(channel=0; channel<max_channels; channel++){
655 		vchannel[channel].paused = toggle;
656 	}
657 }
658 
sound_volume_sample(int channel,int lvolume,int rvolume)659 void sound_volume_sample(int channel, int lvolume, int rvolume){
660 	if(channel<0 || channel>=max_channels) return;
661 	if(lvolume<0) lvolume = 0;
662 	if(rvolume<0) rvolume = 0;
663 	if(lvolume>MAXVOLUME) lvolume = MAXVOLUME;
664 	if(rvolume>MAXVOLUME) rvolume = MAXVOLUME;
665 	vchannel[channel].volume[0] = lvolume;
666 	vchannel[channel].volume[1] = rvolume;
667 }
668 
sound_getpos_sample(int channel)669 int sound_getpos_sample(int channel){
670 	if(channel<0 || channel>=max_channels) return 0;
671 	return FIX_TO_INT(vchannel[channel].fp_samplepos);
672 }
673 
674 //////////////////////////////// ADPCM music ////////////////////////////////
675 
676 static int adpcm_handle = -1;
677 static unsigned char *adpcm_inbuf;
678 static int music_looping = 0;
679 static int music_atend = 0;
680 #define	BOR_MUSIC_VERSION_MONO   0x00010000
681 #define	BOR_MUSIC_VERSION_STEREO 0x00010001
682 #define	BOR_IDENTIFIER "BOR music"
683 
684 #ifndef DC
685 #pragma pack (1)
686 #endif
687 
688 typedef struct{
689 	char	identifier[16];
690 	char	artist[64];
691 	char	title[64];
692 	unsigned int	version;
693 	int		frequency;
694 	int		channels;
695 	int		datastart;
696 }bor_header;
697 
698 #ifndef DC
699 #pragma pack (4)
700 #endif
701 
702 static bor_header borhead;
703 static short loop_valprev[2];
704 static char loop_index[2];
705 static int loop_state_set;
706 static u32 loop_offset;
707 
sound_close_adpcm()708 void sound_close_adpcm(){
709 
710 	int i;
711 
712 	// Prevent any further access by the ISR
713 	musicchannel.active = 0;
714 	for(i=0; i<MUSIC_NUM_BUFFERS; i++){
715 		musicchannel.fp_playto[i] = 0;
716 	}
717 
718 	// Close file...
719 	if(adpcm_handle>=0) closepackfile(adpcm_handle);
720 	adpcm_handle = -1;
721 
722 	if(adpcm_inbuf != NULL){
723 		free(adpcm_inbuf);
724 		adpcm_inbuf = NULL;
725 	}
726 
727 	for(i=0; i<MUSIC_NUM_BUFFERS; i++){
728 		if(musicchannel.buf[i] != NULL){
729 			free(musicchannel.buf[i]);
730 			musicchannel.buf[i] = NULL;
731 		}
732 	}
733 
734 	memset(&musicchannel, 0, sizeof(musicchannelstruct));
735 	memset(&borhead, 0, sizeof(bor_header));
736 
737 	adpcm_reset();
738 	loop_valprev[0] = loop_valprev[1] = 0;
739 	loop_index[0] = loop_index[1] = 0;
740 	loop_state_set = 0;
741 }
742 
sound_open_adpcm(char * filename,char * packname,int volume,int loop,u32 music_offset)743 int sound_open_adpcm(char *filename, char *packname, int volume, int loop, u32 music_offset){
744 
745 	int i;
746 
747 	if(!mixing_inited) return 0;
748 	if(!mixing_active) return 0;
749 
750 	sound_close_music();
751 
752 	// Open file, etcetera
753 	adpcm_handle = openpackfile(filename, packname);
754 	if(adpcm_handle < 0) return 0;
755 
756 	// Read header
757 	if(readpackfile(adpcm_handle, &borhead, sizeof(bor_header)) != sizeof(bor_header)){
758 		goto error_exit;
759 	}
760 
761 	borhead.version = SwapLSB32(borhead.version);
762 	borhead.frequency = SwapLSB32(borhead.frequency);
763 	borhead.channels = SwapLSB32(borhead.channels);
764 	borhead.datastart = SwapLSB32(borhead.datastart);
765 
766 	// Is it really a BOR music file?
767 	if(strncmp(borhead.identifier, BOR_IDENTIFIER, 16)!=0){
768 		goto error_exit;
769 	}
770 
771 	// Can I play it?
772 	if((borhead.version!=BOR_MUSIC_VERSION_MONO && borhead.version!=BOR_MUSIC_VERSION_STEREO) ||
773 	   (borhead.channels!=1 && borhead.channels!=2) ||
774 		borhead.frequency<11025 || borhead.frequency>44100){
775 		goto error_exit;
776 	}
777 	// Seek to beginning of data
778 	if(seekpackfile(adpcm_handle, borhead.datastart, SEEK_SET) != borhead.datastart){
779 		goto error_exit;
780 	}
781 
782 	memset(&musicchannel, 0, sizeof(musicchannelstruct));
783 
784 	musicchannel.fp_period = INT_TO_FIX(borhead.frequency) / playfrequency;
785 	musicchannel.volume[0] = volume;
786 	musicchannel.volume[1] = volume;
787 	musicchannel.channels = borhead.channels;
788 	music_looping = loop;
789 	music_atend = 0;
790 
791 	adpcm_inbuf = malloc(MUSIC_BUF_SIZE / 2);
792 	if(adpcm_inbuf==NULL) goto error_exit;
793 
794 	for(i=0; i<MUSIC_NUM_BUFFERS; i++){
795 		musicchannel.buf[i] = malloc(MUSIC_BUF_SIZE*sizeof(short));
796 		if(musicchannel.buf[i]==NULL) goto error_exit;
797 		memset(musicchannel.buf[i], 0, MUSIC_BUF_SIZE*sizeof(short));
798 	}
799 
800 	loop_offset = music_offset;
801 	music_type = 0;
802 
803 	return 1;
804 	error_exit:
805 	sound_close_music();
806 	closepackfile(adpcm_handle);
807 	return 0;
808 }
809 
sound_update_adpcm()810 void sound_update_adpcm(){
811 
812 	int samples, readsamples, samples_to_read;
813 	short * outptr;
814 	int i, j;
815 
816 	if((adpcm_handle<0) || (music_type!=0)) return;
817 	if(!mixing_inited || !mixing_active){
818 		sound_close_music();
819 		return;
820 	}
821 	if(musicchannel.paused) return;
822 
823 
824 	// Just to be sure: check if all goes well...
825 	for(i=0; i<MUSIC_NUM_BUFFERS; i++){
826 		if(musicchannel.fp_playto[i] > INT_TO_FIX(MUSIC_BUF_SIZE)){
827 			musicchannel.fp_playto[i] = 0;
828 			return;
829 		}
830 	}
831 
832 
833 	// Need to update?
834 	for(j=0, i=musicchannel.playing_buffer+1; j<MUSIC_NUM_BUFFERS; j++, i++){
835 		i %= MUSIC_NUM_BUFFERS;
836 
837 		if(musicchannel.fp_playto[i]==0){
838 			// Buffer needs to be filled
839 
840 			samples = 0;
841 			outptr = musicchannel.buf[i];
842 
843 			if(!music_looping){
844 				if(music_atend){
845 					// Close file when done playing all buffers
846 					if(!musicchannel.active){
847 						sound_close_music();
848 						return;
849 					}
850 				}
851 				else{
852 					readsamples = readpackfile(adpcm_handle, adpcm_inbuf, MUSIC_BUF_SIZE/2) * 2;
853 					if(readsamples <= 0){
854 						// EOF
855 						music_atend = 1;
856 						return;
857 					}
858 					// Play this bit
859 					adpcm_decode(adpcm_inbuf, outptr, readsamples/2, musicchannel.channels);
860 					samples = readsamples;
861 				}
862 			}
863 			else while(samples < MUSIC_BUF_SIZE){
864 				samples_to_read = MUSIC_BUF_SIZE - samples;
865 				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))
866 				{
867 					readsamples = readpackfile(adpcm_handle, adpcm_inbuf, borhead.datastart + loop_offset - seekpackfile(adpcm_handle,0,SEEK_CUR))*2;
868 					adpcm_decode(adpcm_inbuf, outptr, readsamples/2, musicchannel.channels);
869 					loop_valprev[0] = adpcm_valprev(0);
870 					loop_index[0] = adpcm_index(0);
871 					if(musicchannel.channels == SOUND_STEREO){
872 						loop_valprev[1] = adpcm_valprev(1);
873 						loop_index[1] = adpcm_index(1);
874 					}
875 					loop_state_set = 1;
876 					outptr += readsamples;
877 					samples += readsamples;
878 				}
879 				else
880 				{
881 					readsamples = readpackfile(adpcm_handle, adpcm_inbuf, samples_to_read/2) * 2;
882 					if(readsamples < 0){
883 						// Error
884 						sound_close_music();
885 						return;
886 					}
887 					if(readsamples){
888 						adpcm_decode(adpcm_inbuf, outptr, readsamples/2, musicchannel.channels);
889 						outptr += readsamples;
890 						samples += readsamples;
891 					}
892 					if(readsamples < samples_to_read){
893 						// At start of data already?
894 						if(seekpackfile(adpcm_handle,0,SEEK_CUR) == borhead.datastart){
895 							// Must be some error
896 							sound_close_music();
897 							return;
898 						}
899 						// Seek to beginning of data
900 						if(seekpackfile(adpcm_handle, borhead.datastart+loop_offset, SEEK_SET) != borhead.datastart+loop_offset){
901 							sound_close_music();
902 							return;
903 						}
904 						// Reset decoder
905 						adpcm_loop_reset(0, loop_valprev[0], loop_index[0]);
906 						if(musicchannel.channels == SOUND_STEREO){
907 							adpcm_loop_reset(1, loop_valprev[1], loop_index[1]);
908 						}
909 					}
910 				}
911 			}
912 			// Activate
913 			musicchannel.fp_playto[i] = INT_TO_FIX(samples);
914 			if(!musicchannel.active){
915 				musicchannel.playing_buffer = i;
916 				musicchannel.active = 1;
917 			}
918 		}
919 	}
920 }
921 
sound_adpcm_tempo(int music_tempo)922 void sound_adpcm_tempo(int music_tempo)
923 {
924 	musicchannel.fp_period = (INT_TO_FIX(1) * music_tempo / 100) * borhead.frequency / playfrequency;
925 }
926 
sound_query_adpcm(char * artist,char * title)927 int sound_query_adpcm(char *artist, char *title){
928 	if(adpcm_handle<0) return 0;
929 	if(artist) strcpy(artist, borhead.artist);
930 	if(title) strcpy(title, borhead.title);
931 	return 1;
932 }
933 
934 /////////////////////////// Ogg Vorbis decoding ///////////////////////////////
935 // Plombo's Ogg Vorbis decoder for OpenBOR. Uses libvorbisfile or libvorbisidec.
936 
937 #if TREMOR || DC
938 #define ov_decode(vf,buffer,length,bitstream) ov_read(vf,buffer,length,bitstream)
939 #else
940 #define ov_decode(vf,buffer,length,bitstream) ov_read(vf,buffer,length,0,2,1,bitstream)
941 #endif
942 
943 OggVorbis_File *oggfile;
944 vorbis_info *stream_info;
945 int current_section, ogg_handle;
946 
947 // I/O functions used by libvorbisfile
readpackfile_callback(void * buf,size_t len,size_t nmembers,int * handle)948 size_t readpackfile_callback(void *buf, size_t len, size_t nmembers, int *handle)
949 { return readpackfile(*handle, buf, (int)(len * nmembers)); }
closepackfile_callback(void * ptr)950 int closepackfile_callback(void *ptr)
951 {
952 #ifdef VERBOSE
953 	printf ("closepack cb %d\n", *(int*)ptr);
954 #endif
955 
956 	return closepackfile(*(int*)ptr);
957 }
seekpackfile_callback(int * handle,ogg_int64_t offset,int whence)958 int seekpackfile_callback(int *handle, ogg_int64_t offset, int whence)
959 { return seekpackfile(*handle, (int)offset, whence); }
tellpackfile_callback(int * handle)960 int tellpackfile_callback(int *handle)
961 { return seekpackfile(*handle, 0, SEEK_CUR); }
962 
sound_close_ogg()963 void sound_close_ogg(){
964 	ov_clear(oggfile);
965 	oggfile = NULL;
966 	music_type = -1;
967 }
968 
sound_open_ogg(char * filename,char * packname,int volume,int loop,u32 music_offset)969 int sound_open_ogg(char *filename, char *packname, int volume, int loop, u32 music_offset){
970 
971 	int i;
972 
973 	static ov_callbacks ogg_callbacks = {
974 		(size_t (*)(void *, size_t, size_t, void *))  readpackfile_callback,
975 		(int (*)(void *, ogg_int64_t, int))           seekpackfile_callback,
976 		(int (*)(void *))                             closepackfile_callback,
977 		(long (*)(void *))                            tellpackfile_callback
978 	};
979 
980 	if(!mixing_inited) return 0;
981 	if(!mixing_active) return 0;
982 
983 	sound_close_music();
984 #ifdef VERBOSE
985 	printf("trying to open OGG file %s from %s, vol %d, loop %d, ofs %u\n", filename, packname, volume, loop, music_offset);
986 #endif
987 	// Open file, etcetera
988 	ogg_handle = openpackfile(filename, packname);
989 #ifdef VERBOSE
990 	printf ("ogg handle %d\n", ogg_handle);
991 #endif
992 	if(ogg_handle<0) {
993 #ifdef VERBOSE
994 		printf("couldn't get handle\n");
995 #endif
996 		return 0;
997 	}
998 	oggfile = malloc(sizeof(OggVorbis_File));
999 	if (ov_open_callbacks(&ogg_handle, oggfile, NULL, 0, ogg_callbacks)!=0) {
1000 #ifdef VERBOSE
1001 		printf("ov_open_callbacks failed\n");
1002 #endif
1003 		goto error_exit;
1004 	}
1005 
1006 	// Can I play it?
1007 	stream_info = ov_info(oggfile, -1);
1008 	if((stream_info->channels!=1 && stream_info->channels!=2) ||
1009 		stream_info->rate < 11025 || stream_info->rate > 44100){
1010 			sound_close_ogg();
1011 #ifdef VERBOSE
1012 			printf("NOT can i play it\n");
1013 #endif
1014 
1015 			goto error_exit;
1016 	}
1017 
1018 	memset(&musicchannel, 0, sizeof(musicchannelstruct));
1019 
1020 	musicchannel.fp_period = INT_TO_FIX(stream_info->rate) / playfrequency;
1021 	musicchannel.volume[0] = volume;
1022 	musicchannel.volume[1] = volume;
1023 	musicchannel.channels = stream_info->channels;
1024 	music_looping = loop;
1025 	music_atend = 0;
1026 
1027 	for(i=0; i<MUSIC_NUM_BUFFERS; i++){
1028 		musicchannel.buf[i] = malloc(MUSIC_BUF_SIZE*sizeof(short));
1029 		if(musicchannel.buf[i]==NULL){
1030 			sound_close_ogg();
1031 #ifdef VERBOSE
1032 			printf("buf is null\n");
1033 #endif
1034 			goto error_exit;
1035 		}
1036 		memset(musicchannel.buf[i], 0, MUSIC_BUF_SIZE*sizeof(short));
1037 	}
1038 
1039 	loop_offset = music_offset;
1040 	music_type = 1;
1041 
1042 	return 1;
1043 
1044 	error_exit:
1045 	closepackfile(ogg_handle);
1046 	return 0;
1047 
1048 }
1049 
sound_update_ogg()1050 void sound_update_ogg(){
1051 
1052 	int samples, readsamples, samples_to_read;
1053 	short * outptr;
1054 	int i, j;
1055 
1056 	if(!mixing_inited || !mixing_active){
1057 		sound_close_music();
1058 		return;
1059 	}
1060 	if(musicchannel.paused) return;
1061 
1062 	// Just to be sure: check if all goes well...
1063 	for(i=0; i<MUSIC_NUM_BUFFERS; i++){
1064 		if(musicchannel.fp_playto[i] > INT_TO_FIX(MUSIC_BUF_SIZE)){
1065 			musicchannel.fp_playto[i] = 0;
1066 			return;
1067 		}
1068 	}
1069 
1070 
1071 	// Need to update?
1072 	for(j=0, i=musicchannel.playing_buffer+1; j<MUSIC_NUM_BUFFERS; j++, i++){
1073 		i %= MUSIC_NUM_BUFFERS;
1074 
1075 		if(musicchannel.fp_playto[i]==0){
1076 			// Buffer needs to be filled
1077 
1078 			samples = 0;
1079 			outptr = musicchannel.buf[i];
1080 
1081 			if(!music_looping){
1082 				if(music_atend){
1083 					// Close file when done playing all buffers
1084 					if(!musicchannel.active){
1085 						sound_close_music();
1086 						return;
1087 					}
1088 				}
1089 				else while(samples<MUSIC_BUF_SIZE){
1090 					readsamples = ov_decode(oggfile, (char*)outptr, 2*(MUSIC_BUF_SIZE-samples), &current_section) / 2;
1091 					if (readsamples == 0){
1092 						music_atend = 1;
1093 						return;
1094 					} else if (readsamples < 0){
1095 						sound_close_music();
1096 						return;
1097 					}
1098 					outptr += readsamples;
1099 					samples += readsamples;
1100 				}
1101 			}
1102 			else while(samples < MUSIC_BUF_SIZE){
1103 				samples_to_read = MUSIC_BUF_SIZE - samples;
1104 				readsamples = ov_decode(oggfile, (char*)outptr, 2*samples_to_read, &current_section) / 2;
1105 				if(readsamples < 0){
1106 					// Error
1107 					sound_close_music();
1108 					return;
1109 				}
1110 				else if(readsamples > 0){
1111 					outptr += readsamples;
1112 					samples += readsamples;
1113 				}
1114 				else if(readsamples < samples_to_read){
1115 					// At start of data already?
1116 					if(ov_pcm_tell(oggfile) == 0){
1117 						// Must be some error
1118 						sound_close_music();
1119 						return;
1120 					}
1121 					// Seek to beginning of data
1122 					if(ov_pcm_seek(oggfile, loop_offset*2) != 0){
1123 						sound_close_music();
1124 						return;
1125 					}
1126 				}
1127 			}
1128 			// Activate
1129 			musicchannel.fp_playto[i] = INT_TO_FIX(samples);
1130 			if(!musicchannel.active){
1131 				musicchannel.playing_buffer = i;
1132 				musicchannel.active = 1;
1133 			}
1134 		}
1135 	}
1136 }
1137 
sound_ogg_tempo(int music_tempo)1138 void sound_ogg_tempo(int music_tempo){
1139 	musicchannel.fp_period = (INT_TO_FIX(1) * music_tempo / 100) * stream_info->rate / playfrequency;
1140 }
1141 
sound_query_ogg(char * artist,char * title)1142 int sound_query_ogg(char *artist, char *title){
1143 	int i;
1144 	char *current;
1145 	vorbis_comment *comment = ov_comment(oggfile, -1);
1146 
1147 	if (!artist || !title) return 1;
1148 
1149 	for(i=0; i<comment->comments; i++)
1150 	{
1151 		current = comment->user_comments[i];
1152 		if (strncmp("ARTIST=", current, 7) == 0)      strcpy(artist, current+7);
1153 		else if (strncmp("TITLE=", current, 6) == 0)  strcpy(title, current+6);
1154 	}
1155 
1156 	return 1;
1157 }
1158 
1159 /////////////////////////////// INIT / EXIT //////////////////////////////////
1160 
sound_open_music(char * filename,char * packname,int volume,int loop,u32 music_offset)1161 int sound_open_music(char *filename, char *packname, int volume, int loop, u32 music_offset){
1162 	static char fnam[128];
1163 #ifdef VERBOSE
1164 	printf("trying to open music file %s from %s, vol %d, loop %d, ofs %u\n", filename, packname, volume, loop, music_offset);
1165 #endif
1166 	// try opening filename exactly as specified
1167 	if(sound_open_adpcm(filename, packname, volume, loop, music_offset)) return 1;
1168 	if(sound_open_ogg(filename, packname, volume, loop, music_offset)) return 1;
1169 
1170 	// handle adding an extension to the filename
1171 	sprintf(fnam, "%s.bor", filename);
1172 	if(sound_open_adpcm(fnam, packname, volume, loop, music_offset)) return 1;
1173 	sprintf(fnam, "%s.ogg", filename);
1174 	if(sound_open_ogg(fnam, packname, volume, loop, music_offset)) return 1;
1175 	sprintf(fnam, "%s.oga", filename);
1176 	if(sound_open_ogg(fnam, packname, volume, loop, music_offset)) return 1;
1177 
1178 	return 0;
1179 }
1180 
sound_close_music()1181 void sound_close_music(){
1182 	switch(music_type){
1183 		case 0: sound_close_adpcm(); break;
1184 		case 1: sound_close_ogg();
1185 	}
1186 	music_type = -1;
1187 }
1188 
sound_update_music()1189 void sound_update_music(){
1190 	switch(music_type){
1191 		case 0: sound_update_adpcm(); break;
1192 		case 1: sound_update_ogg();
1193 	}
1194 }
1195 
sound_query_music(char * artist,char * title)1196 int sound_query_music(char *artist, char *title){
1197 	switch(music_type){
1198 		case 0:  return sound_query_adpcm(artist, title);
1199 		case 1:  return sound_query_ogg(artist, title);
1200 		default: return 0;
1201 	}
1202 }
1203 
sound_music_tempo(int music_tempo)1204 void sound_music_tempo(int music_tempo){
1205 
1206 	switch(music_type){
1207 		case 0: sound_adpcm_tempo(music_tempo); break;
1208 		case 1: sound_ogg_tempo(music_tempo);
1209 	}
1210 }
1211 
sound_volume_music(int left,int right)1212 void sound_volume_music(int left, int right){
1213 	if(left < 0) left = 0;
1214 	if(right < 0) right = 0;
1215 	if(left > MAXVOLUME*8) left = MAXVOLUME*8;
1216 	if(right > MAXVOLUME*8) right = MAXVOLUME*8;
1217 	musicchannel.volume[0] = left;
1218 	musicchannel.volume[1] = right;
1219 }
1220 
sound_pause_music(int toggle)1221 void sound_pause_music(int toggle){
1222 	musicchannel.paused = toggle;
1223 }
1224 
sound_stop_playback()1225 void sound_stop_playback(){
1226 	int i;
1227 	if(!mixing_inited) return;
1228 	if(!mixing_active) return;
1229 	sound_close_music();
1230 	for(i=0; i<max_channels; i++) sound_stop_sample(i);
1231 	SB_playstop();
1232 	mixing_active = 0;
1233 }
1234 
sound_start_playback(int bits,int frequency)1235 int sound_start_playback(int bits, int frequency){
1236 	int i;
1237 
1238 	if(!mixing_inited) return 0;
1239 
1240 	sound_stop_playback();
1241 
1242 	if(bits!=8 && bits!=16) return 0;
1243 	if(frequency!=11025 && frequency!=22050 && frequency!=44100) return 0;
1244 
1245 #if WIN || LINUX || DARWIN || SYMBIAN
1246 	playbits = bits;
1247 	playfrequency = frequency;
1248 #elif WII
1249 	// Wii only supports 16 bit 32000/48000
1250 	bits = 16;
1251 	frequency = 48000;
1252 	playbits = bits;
1253 	playfrequency = frequency;
1254 #else
1255 	// Most consoles support natively 16/44100
1256 	bits = 16;
1257 	frequency = 44100;
1258 	playbits = bits;
1259 	playfrequency = frequency;
1260 #endif
1261 
1262 	hard_shift = 0;
1263 	if(frequency==22050) hard_shift = 1;
1264 	if(frequency==44100) hard_shift = 2;
1265 
1266 	dmamixpos = PREMIX_SIZE<<hard_shift;
1267 	for(i=0; i<max_channels; i++) sound_stop_sample(i);
1268 	SB_playstop();
1269 	if(!SB_playstart(playbits, playfrequency)) return 0;
1270 
1271 	mixing_active = 1;
1272 	samplesplayed = 0;
1273 	return 1;
1274 }
1275 
1276 // Stop everything and free used memory
sound_exit()1277 void sound_exit(){
1278 
1279 	sound_stop_playback();
1280 	sound_unload_all_samples();
1281 
1282 	if(mixbuf != NULL){
1283 		free(mixbuf);
1284 		mixbuf = NULL;
1285 	}
1286 
1287 #ifdef PSP
1288 	SB_exit();
1289 #endif
1290 #ifdef XBOX
1291 	if(DMAbuf8 != NULL){
1292 		free(DMAbuf8);
1293 		DMAbuf8 = NULL;
1294 	}
1295 #endif
1296 
1297 	mixing_inited = 0;
1298 }
1299 
1300 // Find and initialize SoundBlaster, allocate memory, initialize tables...
sound_init(int channels)1301 int sound_init(int channels){
1302 	int i;
1303 	if(channels < 2) channels = 2;
1304 	if(channels > MAX_CHANNELS) channels = MAX_CHANNELS;
1305 	sound_exit();
1306 
1307 #ifdef XBOX
1308 	DMAbuf8 = (char*)malloc(SB_BUFFER_SIZE << 1 ) ;
1309 	DMAbuf16 = (void*)DMAbuf8;
1310 #endif
1311 
1312 	// Allocate the maximum amount ever possibly needed for mixing
1313 	if((mixbuf = malloc(MIXBUF_SIZE)) == NULL){
1314 
1315 #ifdef PSP
1316 		SB_exit();
1317 #endif
1318 		return 0;
1319 	}
1320 
1321 	max_channels = channels;
1322 	for(i=0; i<max_channels; i++){
1323 		memset(&vchannel[i], 0, sizeof(channelstruct));
1324 	}
1325 
1326 	for(i=0; i<MAX_SAMPLES; i++) sampledata[i].sampleptr = NULL;
1327 	mixing_active = 0;
1328 	mixing_inited = 1;
1329 
1330 	return 1;
1331 }
1332 
1333 // Returns time passed in milliseconds (since last call or start of playback),
1334 // or 0xFFFFFFFF if not available. This function is useful when synchronizing
1335 // stuff to sound.
sound_getinterval()1336 u32 sound_getinterval(){
1337 	u32 msecs;
1338 
1339 	if(!mixing_active) return 0xFFFFFFFF;
1340 
1341 	msecs = 1000 * samplesplayed / playfrequency;
1342 	samplesplayed -= msecs * playfrequency / 1000;
1343 
1344 	return msecs;
1345 }
1346 
1347