ftp.nice.ch/pub/next/unix/audio/cmusic.bs.N.tar.gz#/src/cmusic/ug.sndfile.c

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.