This is SNDindirect.m in view mode; [Download] [Up]
/* SNDindirect.m -- Functions to assist in handling fragmented Sound objects
*
* char *getblock(id aSound, int inskip, int nsamps)
* int putblock(id aSound, int inskip, int nsamps, char *samples)
*
* jwp@silvertone.Princeton.EDU, 4/90
*/
#import <stdio.h>
#import <stdlib.h>
#import <soundkit/Sound.h>
/* Macros:
* MIN(a,b) = minimum of a and b
* DATA(s) = pointer to data in the SNDSoundStruct pointed to by s
* SIZE(s) = number of bytes in the SNDSoundStruct pointed to by s
*/
#define MIN(a,b) ((a > b) ? b : a)
#define DATA(s) (char *)(s) + (s)->dataLocation
#define SIZE(s) (s)->dataSize
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* char *getblock(id aSound, int inskip, int nsamps)
* Gets a block of 'nsamps' sample frames from the Sound object
* 'aSound', starting at frame 'inskip'. These are placed in an
* array a pointer to which is returned (the array is either of
* shorts or floats, depending on the sample type). Returns
* NULL on error.
*/
char *getblock(id aSound, int inskip, int nsamps)
{
int inbytes, nbytes, fragbytes, nchans;
char *samples, *inptr, *outptr;
SNDSoundStruct **slist;
/* Handle some basic errors like: nil sound pointer, no samples,
* too many samples
*/
if (!aSound || !nsamps)
return NULL;
if (inskip + nsamps > [aSound sampleCount])
return NULL;
/* Convert the inskip and nsamps arguments to a byte count by multiplying
* by the number of channels and the number of bytes per sample
*/
nchans = [aSound channelCount];
switch([aSound dataFormat]) {
case SND_FORMAT_LINEAR_16:
inbytes = inskip * nchans * 2;
nbytes = nsamps * nchans * 2;
break;
case SND_FORMAT_FLOAT:
inbytes = inskip * nchans * 4;
nbytes = nsamps * nchans * 4;
break;
default:
return NULL;
}
/* If the sound isn't indirect, then just return a pointer into the
* sound. Otherwise, we have to copy it to an array.
*/
if (![aSound needsCompacting])
samples = (char *)[aSound data] + inbytes;
else {
/* Allocate the array for the samples
*/
if ((samples = malloc(nbytes)) == NULL) {
fprintf(stderr,"getblock: Out of memory\n");
return NULL;
}
/* Get the list of SoundStructs and seek into the sound
*/
for (slist = (SNDSoundStruct **)[aSound data];
inbytes > SIZE(*slist);
slist++)
inbytes -= SIZE(*slist);
/* Use bcopy to move the bytes into the array. Be careful
* not to overshoot fragment boundaries.
*/
inptr = DATA(*slist) + inbytes;
fragbytes = MIN((SIZE(*slist) - inbytes), nbytes);
outptr = samples;
while (nbytes > 0) {
bcopy(inptr,outptr,fragbytes);
outptr += fragbytes;
if ((nbytes -= fragbytes) <= 0)
break;
slist++;
inptr = DATA(*slist);
fragbytes = MIN(SIZE(*slist), nbytes);
}
}
return samples;
}
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* int putblock(id aSound, int inskip, int nsamps, char *samples)
* Copies a block of 'nsamps' contiguous samples from 'samples' to
* 'aSound', starting at 'inskip' samples. This is designed
* to be the reverse of getblock(). Note that if the contiguous
* block was obtained from getblock(), putblock() will always
* "do the right thing". Returns -1 on error, 1 otherwise.
*/
int putblock(id aSound, int inskip, int nsamps, char *samples)
{
int inbytes, nbytes, fragbytes,nchans;
char *outptr;
SNDSoundStruct **slist;
/* Handle some basic errors like: nil sound pointer, no samples
* too many samples, etc.
*/
if (!aSound || !nsamps)
return -1;
if (inskip + nsamps > [aSound sampleCount])
return -1;
/* Convert the inskip and nsamps arguments to a byte count by multiplying
* by the number of channels and the number of bytes per sample
*/
nchans = [aSound channelCount];
switch([aSound dataFormat]) {
case SND_FORMAT_LINEAR_16:
inbytes = inskip * nchans * 2;
nbytes = nsamps * nchans * 2;
break;
case SND_FORMAT_FLOAT:
inbytes = inskip * nchans * 4;
nbytes = nsamps * nchans * 4;
break;
default:
return -1;
}
/* If this is not a fragmented sound, then just copy the samples
* from one array to the other.
*/
if (![aSound needsCompacting]) {
outptr = (char *)[aSound data] + inbytes;
if (outptr != samples)
bcopy(samples,outptr,nbytes);
}
/* Otherwise, distribute the samples among the fragments
*/
else {
/* Get the list of SoundStructs and seek into the sound
*/
for (slist = (SNDSoundStruct **)[aSound data];
inbytes > SIZE(*slist);
slist++)
inbytes -= SIZE(*slist);
outptr = DATA(*slist) + inbytes;
fragbytes = MIN((SIZE(*slist) - inbytes), nbytes);
/* If we don't need to deal with fragmentation, then don't
*/
if (outptr == samples && fragbytes == nbytes)
return 1;
/* Copy the samples into the various sound fragments.
*/
while (nbytes > 0) {
bcopy(samples,outptr,fragbytes);
outptr += fragbytes;
if ((nbytes -= fragbytes) <= 0)
break;
slist++;
outptr = DATA(*slist);
fragbytes = MIN(SIZE(*slist), nbytes);
}
}
return 1;
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.