This is mixSounds.m in view mode; [Download] [Up]
#import <stdio.h> #import <soundkit/Sound.h> /* 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) /* mixSounds() * Mixes part of one sound onto another sound. * This function will work with fragmented Sound objects. * Returns -1 on error, 1 if OK. * BUG: Only works with mono, short files. * jwp@silvertone.Princeton.EDU, 2/23/90 */ int mixSounds(inSound,outSound,inskip,outskip,nsamps) id inSound; /* Input Sound object */ id outSound; /* Output Sound (the one we mix to) */ int inskip; /* First sample from input sound */ int outskip; /* First sample from output sound */ int nsamps; /* Total number of samples to mix */ { SNDSoundStruct **inList, **outList; /* Pointers to the * lists of Sound * fragments */ SNDSoundStruct *fakein[2], *fakeout[2]; /* Phoney fragment * lists for un- * fragmented Sounds */ SNDSoundStruct *inStruct, *outStruct; /* Pointers to the * actual fragments */ short *in, *out; /* Pointers to data */ int insamps,outsamps; /* Number of samples in fragments */ int n, blocksize; /* For loop control */ int i = 0; //fprintf(stderr,"mixSounds: inskip:%d outskip:%d nsamps:%d\n",inskip,outskip,nsamps); /* Check the format of the Sound objects. If they're fragmented, * then set inStruct to point to the fragment list. Otherwise, * make a fake fragment list and shove the SNDSoundStruct pointer * into it (this simplifies things later on). */ if ([inSound needsCompacting]) inList = (SNDSoundStruct **)[inSound data]; else { fakein[0] = [inSound soundStruct]; fakein[1] = NULL; inList = fakein; } if ([outSound needsCompacting]) outList = (SNDSoundStruct **)[outSound data]; else { fakeout[0] = [outSound soundStruct]; fakeout[1] = NULL; outList = fakeout; } inStruct = *inList++; outStruct = *outList++; /* Get a starting sample pointer for both sounds by going * through their fragment lists until we hit the right spot. * Set up insamps and outsamps to give the number of samples left * in the first fragment. */ while (inskip) { //fprintf(stderr,"mixSounds: inSound fragment %d\n",i++); if (NSAMPS(inStruct) > inskip) break; //fprintf(stderr,"\t\t... going to next fragment\n"); 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; while (outskip) { //fprintf(stderr,"mixSounds: outSound fragment %d\n",i++); if (NSAMPS(outStruct) > outskip) break; //fprintf(stderr,"\t\t... going to next fragment\n"); outskip -= NSAMPS(outStruct); if ((outStruct = *outList++) == NULL) { fprintf(stderr,"mixSounds: outskip too large\n"); return -1; } } out = (short *)DATA(outStruct) + outskip; outsamps = NSAMPS(outStruct) - outskip; /* # of samples left in frag */ /* Main loop: * Here we take the smallest of three numbers: the number of samples in * the input fragment, the number of samples in the output fragment, * or the number of samples left to mix. We then mix this many samples. * Then reset all the numbers for the next pass. Each block of samples * is guaranteed continguous, so that we can do the mixing as fast as * possible. */ while (nsamps > 0) { blocksize = MIN(insamps,outsamps); fprintf(stderr,"mixSounds: blocksize:%d nsamps:%d n:%d\n", blocksize,nsamps,MIN(blocksize,nsamps)); 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); } if (!(outsamps -= blocksize)) { if ((outStruct = *outList++) == NULL) break; outsamps = NSAMPS(outStruct); out = (short *)DATA(outStruct); } nsamps -= blocksize; } return 1; }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.