This is ug.sndfile.c in view mode; [Download] [Up]
/* sndfile - Soundfile Lookup Generator * (NeXT version, frm@ucsd.edu, 9-nov-92) * * Because NeXT software generally treats soundfiles as data structures in * memory, opening many large soundfiles at the same time with sndfile (as * mix-minded users are likely to do) caused the associated cmusic process * to grow into and sometimes beyond the limits of virtual memory, causing * system thrashing (at best). The method used here is therefore to treat * soundfiles as normal files, allowing as many to be open at the same time * as UNIX will allow (see <sys/param.h>). * * For use with the sndfile unit generator, soundfiles must be in linear * 16-bit PCM format. * * The following score, for example, loops samples 5000 through 30000 from * channel 0 (the first!) of soundfile music.snd (which is 68032 samples long) * backwards at the original pitch (via incr = p6 = -1), while applying an * overall exponential amplitude envelope to the note (via seg), for a * duration of twice the original soundfile (assuming that the sampling rate * of cmusic and the soundfile match). (To loop the whole soundfile instead, * simply replace 5000 by 0 and 30000 by -1). * * #include <carl/cmusic.h> * set list ; * * var 0 s1 "music.snd"; var 0 v1 68032 ; * ins 0 vng; * seg b2 p5 f1 d 0; {p5 - peak amp} * sndfile b1 b2 p6 s1 0 5000 30000 d d d d d ; {p6 - increment} * out b1; * end; * * GEN4(f1) 0,0 (-20) .1,1 (0) .95,1 (-20) 1,0; * * { p1 p2 p3 p4 p5 p6 } * { cmd start ins dur amp incr } * note 0 vng 2*(v1)S -6dB -1 ; * * ter; */ #include "mm.head.h" #include "ug.head.h" #if defined nextsf #import <sound/sound.h> SNDSoundStruct * snd ; FILE * SFFPtr ; # endif nextsf #define AMP 1 #define INCR 2 #define FNAME 3 #define CHANNEL 4 #define FSTART 5 #define FEND 6 #define FRAME 7 #define NCHAN 8 #define SAMPS 9 #define OFFSET 10 #define FILEPTR 11 sndfile #if defined nextsf UGHEAD { UGINIT ; long nchan, size, offset, last, chan, nsamp ; FILE *fptr ; float interpsnd() ; double frame ; /* * Read header info from file and check for counterindications */ if( STARTNOTE ) { SFFPtr = NULL ; if ( (fptr = FPLOC(FILEPTR) = fopen( SLOC(FNAME), "r" )) == NULL) { Error++ ; PROUT( "SNDFILE: Error opening file '%s'", SLOC(FNAME) ) ; return ; } snd = (SNDSoundStruct *) calloc( 1, sizeof(SNDSoundStruct) ) ; fread( snd, sizeof(SNDSoundStruct), 1, fptr ) ; if ( snd->magic != SND_MAGIC ) { Error++ ; PROUT( "SNDFILE: '%s' not a soundfile", SLOC(FNAME) ) ; return ; } if ( snd->dataFormat != SND_FORMAT_LINEAR_16 ) { Error++ ; PROUT( "SNDFILE: '%s' not linear 16-bit format", SLOC(FNAME) ) ; return ; } if( VAL(CHANNEL) + 1 > snd->channelCount ) { Error++ ; PROUT( "SNDFILE: File doesn't contain '%.0f' channels", VAL(CHANNEL) + 1. ) ; return ; } /* * The following warning can get obnoxious and may be safely commented out * by users with unfailing memory for details. */ if ( snd->samplingRate != Srate ) { PROUT( "SNDFILE WARNING: '%s' sampling rate != cmusic rate", SLOC(FNAME) ) ; } chan = VAL(CHANNEL) ; nchan = LVAL(NCHAN) = snd->channelCount ; LVAL(SAMPS) = snd->dataSize >> 1 ; /* * file byte offset value includes channel offset */ LVAL(OFFSET) = snd->dataLocation + ( ( ( ( (long) VAL(FSTART)) * nchan ) + chan ) << 1 ) ; free( snd ) ; VAL(FRAME) = VAL(FSTART) ; } fptr = FPLOC(FILEPTR) ; nsamp = LVAL(SAMPS) ; chan = VAL(CHANNEL) ; nchan = LVAL(NCHAN) ; offset = LVAL(OFFSET) ; if( VAL(FEND) < 0. ) VAL(FEND) = nsamp/nchan - 1 ; size = VAL(FEND) - VAL(FSTART) + 1 ; last = VAL(FEND) ; frame = VAL(FRAME) ; UGLOOP { VAL(OUT)++ = VAL(AMP) * interpsnd( fptr, frame, size, last, nchan, offset ) ; frame += VAL(INCR) ; while ( frame > VAL(FEND) ) frame -= size ; while ( frame < VAL(FSTART) ) frame += size ; UGEND(1) ; } VAL(FRAME) = frame ; if ( ENDNOTE ) fclose( fptr ) ; } /* * Do some lite buffering to help out poor UNIX with music * (UNIX doesn't skip merrily forwards and/or backwards * in soundfiles, for example) */ #define bufSize 1024 float interpsnd( fp, frame, size, last, nchan, offset ) FILE * fp ; double frame ; long size, last, nchan, offset ; { short v1, v2 ; long intPart, block, blockOffset, pos ; double fracPart ; static float floatsam = 1./32767. ; static long blockSize, Fblock = -1 ; static short Fbuf[bufSize] ; /* * If block already in Fbuf isn't what we need, mark it invalid */ if ( fp != SFFPtr ) { blockSize = bufSize/nchan ; SFFPtr = fp ; Fblock = -1 ; } intPart = (long) frame ; block = (pos = intPart*nchan)/blockSize ; blockOffset = pos%blockSize ; if ( block != Fblock ) { fseek( fp, block*blockSize*sizeof(short) + offset, 0 ) ; fread( Fbuf, sizeof(short), blockSize, fp ) ; Fblock = block ; } v1 = Fbuf[blockOffset] ; /* * perform linear interpolation as needed */ if ( fracPart = frame - intPart ) { if ( ++intPart > last ) intPart -= size - 1 ; block = (pos = intPart*nchan)/blockSize ; blockOffset = pos%blockSize ; if ( block != Fblock ) { fseek( fp, block*blockSize*sizeof(short) + offset, 0 ) ; fread( Fbuf, sizeof(short), blockSize, fp ) ; Fblock = block ; } v2 = Fbuf[blockOffset] ; return( ( v1 + fracPart*(v2 - v1) )*floatsam ) ; } else /* * end of interpolator */ return( v1*floatsam ) ; } # endif nextsf # if !defined nextsf UGHEAD { UGINIT ; fprintf( stderr," Unimplemented Unit Generator: SNDFILE\n" ) ; } #endif !nextsf
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.