#import <stdio.h>
#import <soundkit/Sound.h>
/* castration of jwp's mixSounds.  To copy segment of fragmented sound to 
 * single buffer */
/* Shorthand macros to handle SNDSoundStructs.
 * NSAMPS(s) = number of samples in fragment s
 * DATA(s) = Pointer to samples in fragment s
 */
#define NSAMPS(s)	(s->dataSize / 2)
#define DATA(s)		((char *)s + s->dataLocation)
#define MIN(a,b)	((a > b) ? b : a)
#define CHANS(s)  s->channelCount

int fragSounds(inSound,outSound,inskip,nsamps)
id inSound;			/* Input Sound object */
short  *outSound;		/* Output Sound (the one we mix to) */
int inskip;			/* First sample from input sound */
int nsamps;			/* Total number of samples to mix */
{
	SNDSoundStruct **inList;		/* Pointers to the
						 * lists of Sound
						 * fragments*/
	SNDSoundStruct *fakein[2];		/* Phoney fragment
						 * lists for un-
						 * fragmented Sounds*/
	SNDSoundStruct *inStruct;		/* Pointers to the
						 * actual fragments*/
	short *in, *out;		/* Pointers to data */
	int insamps;		        /* Number of samples in fragments */
	int n, blocksize;		/* For loop control */
	int i = 0;
	if ([inSound needsCompacting])
		inList = (SNDSoundStruct **)[inSound data];
	else {
		fakein[0] = [inSound soundStruct];
		fakein[1] = NULL;
		inList = fakein;
	}
	inStruct = *inList++;
	
	while (inskip) {
		if (NSAMPS(inStruct) > inskip)
			break;
		inskip -= NSAMPS(inStruct);
		if ((inStruct = *inList++) == NULL) {
			fprintf(stderr,"mixSounds: inskip too large\n");
			return -1;
		}
	}
	in = (short *)DATA(inStruct) + inskip;
	insamps = NSAMPS(inStruct) - inskip;	/* # of samples left in frag */

	i=0;
	out = outSound;
	if(CHANS(inStruct) == 2) {
		while (nsamps > 0) {
			blocksize = insamps;

			for (n = MIN(blocksize,nsamps); n; n--, out++, in++)
				*out = *in;
			if (!(insamps -= blocksize)) {
				if ((inStruct = *inList++) == NULL)
					break;
				insamps = NSAMPS(inStruct);
				in = (short *)DATA(inStruct);
				}
				nsamps -= blocksize;
			}
		}
	else {
		while (nsamps > 0) {
			blocksize = insamps;

			for (n = MIN(blocksize,nsamps); n; n-=2, out+=2, in++) {
				*out = *in;
				*(out+1) = *in;
				}
			if (!(insamps -= blocksize)) {
				if ((inStruct = *inList++) == NULL)
					break;
				insamps = NSAMPS(inStruct);
				in = (short *)DATA(inStruct);
				}
				nsamps -= blocksize;
			}
		}
	return 1;
}
