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

This is mm.sndout.c in view mode; [Download] [Up]

#include "mm.head.h"
#include "m.exts.h"
#include <carl/carl.h>
#include <carl/defaults.h>
#include <math.h>
#include <sys/file.h>

#ifdef nextsf
#import <sound/sound.h>
SNDSoundStruct *snd ;
/* int fd = -1 ;	this changed to a global var ofiledes - sfl */
#endif

sndout(){
     static int otty;
     register long i,n;
     register float *Fout;
     register short *Sout;
     static long scount = 0, dcount = 0, lastclipped= 0, dclipped = 0;
     static float dmax = 0.0, aval;
     static char first;

    otty = isatty(1);
    n = Ngen*Nchan;
    if( (scount += Ngen) >= Srate)scount -= Srate;
    if(scount < Ngen){
	dcount++;
	PROUT(":%d",dcount);
	PROUT("(%f)",dmax);
	if(Timer)fprintf(stderr, ":%d(%f)",dcount,dmax);
	dmax = 0.0;
	dclipped = Clipped - lastclipped;
	if(dclipped)PROUT("[%d]", dclipped);
	lastclipped = Clipped;
	if(!(dcount%5))PROUT("\n",stderr);
    }

    if(Spaceon && Revscale > 0.0)Greverb();
#ifdef nextsf
	if( Outfilename != 0 && !first ) {
	    first++;
	    SNDAlloc(&snd,0,SND_FORMAT_LINEAR_16,Srate,Nchan,4);

/* file descriptor for the following open must be global so that the */
/* main routine can close and reopen it for updating the header - sfl */
	    if((ofiledes = open(Outfilename, O_CREAT | O_WRONLY | O_TRUNC, 0644 )) < 0) {
		fprintf(stderr,"Unable to write '%s'\n", Outfilename) ;
		exit(-1) ;
	    }
	    SNDWriteHeader(ofiledes,snd);
	}
#else
	if(Header && !otty) {
	    if (!first && strlen( Outfilename ) > 0 ) {
		    char srate[32], nchan[32];

		    first++;
		    sprintf(srate, "%d", Srate);
		    sprintf(nchan, "%d", Nchan);
		    if (!Floatout)
			    set_sample_size(sizeof(short));
		    if (stdheader(stdout, Infilename, srate, nchan, 
			    Floatout ? H_FLOATSAM : H_SHORTSAM))
				    fprintf(stderr, "can't create header\n");
		    if (putheader(stdout))
			    fprintf(stderr, "can't write header\n");
	    }
	}
#endif
    Fout = Outblock; Sout = Sampout;
    for(i=0; i<n; i++,Sout++,Fout++){
	aval = *Fout >= 0 ? *Fout : -( *Fout) ;
	if(aval > Maxamp) Maxamp = aval;
	if(aval > dmax) dmax = aval;
	if(*Fout > 1.0 && Clip){*Fout = 1.0; Clipped++;}
	if(*Fout < -1.0 && Clip){*Fout = -1.0; Clipped++;}
	if(!Floatout) *Sout = *Fout * 32767.0;
    }
	if(Nooutput) return ;

#ifdef nextsf
    if(ofiledes >= 0) 
	write(ofiledes,Sampout, n << 1);

    else {
	if(otty){
	    if(Floatout)	for(i=0; i<n; i++) printf("%8.8f\n",*(Outblock+i));

	    else		for(i=0; i<n; i++)printf("%d\n",*(Sampout+i));
	}
	else {
	    if(Floatout)	fputfbuf(Outblock,n,stdout);

	    else		fputsbuf(Sampout,n,stdout);
	}
    }
#else
    if(otty){
	if(Floatout)for(i=0; i<n; i++) printf("%8.8f\n",*(Outblock+i));
	 else for(i=0; i<n; i++)printf("%d\n",*(Sampout+i));
    }
    else {
	if(Floatout) fputfbuf(Outblock,n,stdout);
	 else fputsbuf(Sampout,n,stdout);
    }
#endif
}
/*
 * the cmusic global reverberator (input produced by space unit generator)
 */
#define NCF 31 /* Number of parallel comb filters (note comb routine setup) */
Greverb(){
 register float *Out = Outblock, *Grev = Grevblock, gout;
 register int i,f;
 float allpass(), comb();
 float val, aval;
 static long tailcount = 0;

    for(i=0; i<Ngen; i++, Grev++){
	for(gout=0., f=0; f<NCF; f++) gout += comb(f,*Grev);
	for(f=0; f<Nchan; f++){
	    val = allpass(f,gout);
	    val *= Revscale;
	    aval = val >= 0 ? val : -val ;
	    if(aval > Maxreverb)Maxreverb = aval;
	    if(aval > Revthresh)tailcount = 0;
	    if(Spacereset){Spacereset = Spaceon = 0; return;}
	    if(++tailcount > Srate){Spacereset = 1; tailcount = 0;}
	    *Out++ += val;
	}
    }
}
/*
 * comb filters with lowpass loops
 */
float comb(n,x) int n; float x; {

  static long dlen[] = {43, 127, 211, 223, 227, 251, 263, 269, 271, 281, 293, 379, 457, 467, 487, 523, 571, 577, 587, 593, 599, 607, 613, 659, 709, 719, 727, 739, 751, 773, 797};

  static float g1[] = {.71, .5, .65, .5, .65, .5, .6, .5, .6, .5, .5, .5, .5, .5, .5, .5, .5, .5, .5, .5, .5, .5, .5, .5, .5, .5, .5, .5, .5, .5, .5};

 static long now[NCF], first = 1;
 static float *dbuf[NCF], g2[NCF], zm1[NCF];
 register float t, y;
 register int i, j;
    
    if(first) {

	if(Color == 1) {		// less bright than default

	    for(i = 0; i < NCF; i++) {

		if(i < 18)	g1[i] = 0.5;

		else		g1[i] = 0.75;
	    }
	}
	if(Color == 2) {		// even less bright

	    for(i = 0; i < NCF; i++) {

		if(i < 18)	g1[i] = 0.5;

		else		g1[i] = 0.95;
	    }
	}
	else if(Color != 0) {		// the flat response

	    for(i = 0; i < NCF; i++)	g1[i] = 0.25;
	}
	for(i=0; i<NCF; i++) {

	    dlen[i] = Srate*dlen[i]/10000.;			// JS -- was 1000
	    g1[i] = (Srate*g1[i]/50000.) ;			// JS -- was /25000
	    g2[i] = T60mult*(1. - g1[i]);
	    zm1[i] = now[i] = 0;
	    dbuf[i] = (float *) calloc(dlen[i], sizeof(float));
	    first = 0;
	}
    }
    if(Spacereset){
	for(i=0; i<NCF; i++){
	    for(j=0; j<dlen[i]; j++)dbuf[i][j] = 0.0;
	    zm1[i] = 0.0;
	    now[i] = 0;
	}
	return(0.0);
    }
    y = dbuf[n][now[n]];
    t = y + zm1[n]*g1[n];
    zm1[n] = t;
    dbuf[n][now[n]] = x + t*g2[n];
    if( (now[n] += 1) >= dlen[n]) now[n] = 0;
    return( (float) y);
}
/*
 * the famous one-multiply allpass filter
 */
float allpass(n,x) int n; float x; {
 static int dlen[] = {6,7,8,9}; /* delay lengths */
 static float g[] = {.7,.71,.72,.73}; /* loog gains */
 static int now[NCF], first = 1;
 static float *dbuf[NCF];
 register float t1, t2;
 register int i, j;
    
    if(first) for(i=0; i<Nchan; i++){
/* make delays slightly different */
	dlen[i] = Srate*dlen[i]/1000. + 3*i; 
	now[i] = 0;
	dbuf[i] = (float *) calloc(dlen[i], sizeof(float));
	first = 0;
    }
    if(Spacereset){
	for(i=0; i<Nchan; i++){
	    for(j=0; j<dlen[i]; j++)dbuf[i][j] = 0.0;
	    now[i] = 0;
	}
	return(0.0);
    }
    t1 = dbuf[n][now[n]];
    dbuf[n][now[n]] = (t2 = (x - t1)*g[n]) + x;
    if( (now[n] += 1) >= dlen[n]) now[n] = 0;
    return( (float) (t1 + t2) );
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.