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.