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.