ftp.nice.ch/pub/next/unix/audio/Cmix.N.s.tar.gz#/cmix/lpc/synthesis/lpcplay.c

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

#include "../../H/ugens.h"
#include "../../H/sfheader.h"
#include <math.h>
#include <stdio.h>
#define RESIDAMP     0
#define RMSAMP       1
#define THRESH       2
#define PITCH        3

int anal;
float cq,outold;
extern SFHEADER sfdesc[NFILES];

#define MAXPOLES 60
#define MAXVALS 10000
int framsize;
int fprec;
int recsize;
int bprec;
int bpframe;
int npolem1;
int anal;
int i;
float cq,outold,maxdev;
float perperiod = 1.0;
float FloatJunk;
float cutoff;
extern SFHEADER sfdesc[NFILES];
char dataset_name[80];
float thresh,randamp,randoff,unvoiced_rate;
int npoles;
float risetime,decaytime;

double lpcplay(p,n_args)
float *p;
{
        float amp,si,hn,phs,*f,srd2,magic,d,warpset();
        float c[MAXPOLES+4],past[MAXPOLES*2],frames,frameno,ampmlt,errno;
        int frame1;
        float ballpole(),alpvals[MAXVALS],buzvals[MAXVALS],pchval[MAXVALS];
        float *cpoint;
        float x,transposition,newpch;
        double shift();
        int jcount,seed,i,nsamps,counter;
        int nn,lastfr;
        float transp,lasttr,tranincr;
        float cps,tblvals[2],weight();
        float rsnetc[9];
        int reson_is_on;
        float cf_fact,bw_fact;
        float evals[5];
        float *f1;
        float actualcps,actualweight;
        float peak;
        int jj,datafields,unit;

        if(!n_args) {
                printf(" p[0]=starting time, p[1]=duration, p[2]=pitch,p[3]=frame1, p4=frame2 p[5]=amp, p[6]=warp p7=resonbw, p8=resoncf p9--> pitchcurves\n");
                return;
        }
	
	unit = 1;  /* outputfile */
        f1 = floc(2);
        sbrrand(.1);
        for(i=0; i<npoles*2; i++) past[i] = 0;

        if(anal <=0 ) {
                printf("%d !!!No open dataset!",anal);
                closesf();
        }
        srd2 = SR/2.;
        magic = 512./SR;
        jcount = phs = counter = 0; 
        datafields = 10; /* number of fields before pitch curves */
        seed = .1;
        cpoint = c + 4;
        p[1] = (p[1] > 0.) ? p[1] : ((p[4] - p[3] + 1.)/112.);
        evset(p[1],risetime,decaytime,2,evals);
        nsamps = setnote(p[0],p[1],unit);
        frames = p[4] - p[3] + 1.;
        frame1 = (int)p[3];
        for(i=p[3]; i<= p[4]; i++) {
                d = i;
                if(getfr(d,c) < 0) break;
                pchval[i - (int)p[3]] = (c[PITCH] ? c[PITCH] : 256.);
                /* just in case I am using datasets with no pitch value
                   stored */
        }
        /*p[4] = i; */
        actualweight = weight(p[3],p[4],thresh);
        if(!actualweight) actualweight = cpspch(p[2]);
        if(ABS(p[2]) < 1.)  {
                FloatJunk=(p[2]/.12);
                FloatJunk=pow(2.0,FloatJunk);
                transposition=FloatJunk;
                transposition = (pow(2.0,(p[2]/.12)));
        }
        else if(p[2] > 0) transposition = cpspch(p[2])/actualweight;
        else transposition = cpspch(-p[2]);  /* flat pitch */
        if((n_args <= datafields) && (p[2] > 0)) {
                printf("\nOverall transposition: %f, actualweight = %f\n",transposition,actualweight);
                if(maxdev) 
			readjust(maxdev,pchval,p[3],p[4],thresh,actualweight);
                for(i=frame1;i<=(int)p[4];i++) {
                        pchval[(i - frame1)] *= transposition;
                }
        }
        else {
                nn=datafields-1;
                lastfr=frame1;
                lasttr=transposition;
                while((nn+=2)<n_args) {
                        if(ABS(p[nn+1]) < 1.) {
                                transp = pow(2.0,(p[nn+1]/.12));
                        }
                        else {
                                transp = cpspch(ABS(p[nn+1]))/weight((float)lastfr,(p[nn]+1.),thresh);
                        }
                        tranincr=(transp-lasttr)/(p[nn]-lastfr);
                        transp=lasttr;
                        for(i=lastfr;i<(int)p[nn];i++) {
                                pchval[i-frame1]*=transp;
                                transp+=tranincr;
                        }
                        lastfr=p[nn];
                        lasttr=transp;
                }
                if(p[n_args-2] < p[4]) {
                /* last frame in couplets wasn't last frame in batch, so use
                                                base value from there to the end */
                        transp = transposition;
                        for(i=lastfr;i<(int)p[4];i++) {
                                pchval[i-frame1]*=transp;
                        }
                }
        }
        tableset(p[1],(int)(p[4]-p[3]+1),tblvals);
        amp = p[5];
        d = p[6];
        actualweight = weight(p[3],p[4],thresh);
        actualcps = cpspch(ABS(p[2]));
	
       //d = (d>1.) ? shift(actualweight,actualcps,(float)SR) : p[6];
       d = (d>1.) ? .0001 : p[6];

        /* note, dont use this feature unless pitch is specified in p[2]*/

        f = (float *)floc(1);
        for(i=0; i<9; i++) rsnetc[i]=0;
        reson_is_on = p[7] ? 1 : 0;
        cf_fact = p[7];
        bw_fact = p[8];

        warpinit();
        for(i=nsamps; i>0; i -=counter) {
                frameno = ((float)(nsamps - i)/nsamps)*frames + frame1;
                if(getfr(frameno,c) == -1) goto out;
                errno = (c[THRESH] > thresh) ? 0 : 1;  
                ampmlt = (errno) ? amp * c[RESIDAMP] : amp * c[RESIDAMP] * randamp;
                if(c[RMSAMP] < cutoff) ampmlt = 0;
                cps = tablei(nsamps-i,pchval,tblvals);
                newpch = cps;
                if((p[2]< 0) &&  (ABS(p[2]) >= 1)) newpch = transposition;
                if(reson_is_on) { rszset(cf_fact*cps, bw_fact*cf_fact*cps,1.,rsnetc);
			//printf("%f %f %f %f\n",cf_fact*cps, bw_fact*cf_fact*cps,cf_fact,bw_fact,cps);
			}
                si = newpch * magic;
                ampmlt *= evp(nsamps-i,f1,f1,evals);

                if(d)   ampmlt *=  warpset(d,cpoint);
                hn = (int)(srd2/newpch)-2;
                counter = (float)(SR/(newpch * perperiod) ) * .5;
                counter = (counter > i) ? i : counter;
/*printf("%f %f %f %f %d\n",frameno,errno,ampmlt,newpch,counter); */
                if(counter <= 0) break;

                if(errno) 
                        bbuzz(ampmlt,si,hn,f,&phs,buzvals,counter);
                else
                        brrand(ampmlt,buzvals,counter);
                if(d) {
			
			d = (p[6] > 1.) ? shift(c[3],newpch,(float)SR) : p[6];
//printf("d=%f %f %f\n",c[3],newpch,d);        
		 /*************
			d = ABS(d) > .2 ? SIGN(d) * .15 : d;
                        ***************/
                        bwarppol(buzvals,past,d,cpoint,alpvals,counter);
                }
                else
                {
                        ballpole(buzvals,&jcount,npoles,
                        past,cpoint,alpvals,counter);
                }
                if(reson_is_on) bresonz(alpvals,rsnetc,alpvals,counter);

                baddout(alpvals,unit,counter);

        }
out:    endnote(unit);
}
double lpcin(p,n_args)
float *p;
{
	float amp,si,hn,phs,*f,srd2,magic,d,warpset();
	float c[MAXPOLES+4],past[MAXPOLES*2],frames,frame1,frameno,ampmlt,errno;
	float ballpole(),alpvals[2048],buzvals[2048];
	float randamp,randoff;
	float *cpoint;
	float x,transposition,newpch;
	int jcount,seed,i,nsamps,counter;
	float tblvals[2];
	int nread,input, output, j,k,count;


	if(n_args != 7) {
printf(" incorrect argument list: p[0]=starting time, p[1]=duration,p[2]=frame1, p[3]=frame2 p[4]=amp,p[5]=d,p[6]=inputskip\n");
		return;
	}
	if(anal <= 0) { printf("No lpc dataset has been opened\n"); return;}
	input = 0; output=1;
	if(sfchans(&sfdesc[output]) != 1) { 
		printf("Output file must have 1 channel only\n");
		return;
		}
	if(sfchans(&sfdesc[input]) != 1) { 
		printf("Input file must have 1 channel only\n");
		return;
		}
	
	for(i=0; i<npoles*2; i++) past[i] = 0;

	srd2 = SR/2.;
	magic = 512./SR;
	jcount = phs = counter = 0; 
	randamp = .1;
	seed = .1;
	cpoint = c + 4;

	nsamps = setnote(p[0],p[1],output);
                 setnote(p[6],p[1],input);
	frames = p[3] - p[2] + 1.;
	frame1 = p[2];
	amp = p[4];
	d = p[5];

	if(anal <=0 ) {
		printf("No open dataset!");
		return;	
	}

	warpinit();
	for(i=nsamps; i>0; i -=counter) {
			frameno = ((float)(nsamps - i)/nsamps)*frames + frame1;
			if(getfr(frameno,c) == -1) break;
			ampmlt = c[0];
			newpch = c[3];
			counter = (float)(SR/newpch);
			counter = (counter > i) ? i : counter;
			if(counter <= 0) break;

			nread=bgetin(buzvals,input,count=counter*sfchans(&sfdesc[input]));
			if(!nread)  break;
			if(d) {
                                ampmlt *=  warpset(d,cpoint);
                               bwarppol(buzvals,past,d,cpoint,alpvals,counter);
			}
			else
				ballpole(buzvals,&jcount,npoles,
		               		past,cpoint,alpvals,counter);

			bmultf(alpvals,ampmlt,counter);
			bwipeout(alpvals,output,counter); 
		}
	endnote(output);
}

float warppol(sig,past,d,c)
float sig,*past,d,*c;
{
        float temp1,temp2;
        int n;

        temp1 = past[npolem1];
        past[npolem1] = cq * outold - d * past[npolem1];
        for(n=npoles-2; n>=0; n--) {
                temp2 = past[n];
                past[n] = d * (past[n+1] - past[n]) + temp1;
                temp1 = temp2;
        }
        for(n=0;n<npoles;n++)  sig += c[n] * past[n];
        outold = sig;
        return(sig);
}
float warpset(d,c)     
float d,*c;
{
        int m;
        float cl;

        for(m=1; m<npoles; m++)   c[m] += d * c[m-1];
        cl = 1./(1.-d * c[npolem1]);
        cq = cl * (1. - d * d);
        return(cl);
}
warpinit()
{
        outold = 0;
}
bwarppol(sig,past,d,c,out,nvals)
float *sig,*past,d,*c,*out;
{
        float temp1,temp2;
        int i,n;
        for(i=0; i<nvals; i++) {
                temp1 = past[npolem1];
                past[npolem1] = cq * outold - d * past[npolem1];
                for(n=npoles-2; n>=0; n--) {
                        temp2 = past[n];
                        past[n] = d * (past[n+1] - past[n]) + temp1;
                        temp1 = temp2;
                }
                for(n=0;n<npoles;n++)  *sig += c[n] * past[n];
                *out++ = outold = *sig++;
        }
}
getfr(frameno,c)
float frameno,*c;
{
        int frame,i,j;
        static float array[22*(MAXPOLES+4)];
        float fraction;
        static int oldframe = 0;
        static int endframe = 0;
        frame = (int)frameno;
        fraction = frameno - (float)frame;
        if(!((frame >= oldframe) && (frame < endframe))) {
                if(lseek(anal,((long)frame*(long)bpframe),0) == -1) {
                        fprintf(stderr,"bad lseek on analysis file \n");
                        return(-1);
                } 
                if(read(anal,(char *)array,bprec) <= 0) {
                        fprintf(stderr,"reached eof on analysis file \n");
                        return(-1);
                }
                oldframe = frame;
                endframe = oldframe + fprec - 1;
        }
        for(i=(frame-oldframe)*framsize,j=0; j<framsize; i++,j++)  
                *(c+j) = *(array+i) + fraction * (*(array+i+framsize) 
                    - *(array+i));
        return(0);
}
static  long    randx = 1;

/*
srrand(x)
unsigned x;
{
        randx = x;
}
*/
float table(nsample,array,tab)

long nsample;
float *array,*tab;

{
        register loc = ((float)(nsample)/(*tab)) * *(tab+1);
        if(loc >= *(tab+1)) loc = *(tab+1);
        return(*(array + loc));
}
float weight(frame1,frame2,throsh)
float frame1,frame2,throsh;
{
        float c[MAXPOLES+4];
        int i;
        float xweight,sum;
        xweight = sum = .001;
        for(i=(int)frame1; i<(int)frame2; i++) {
                getfr((float)i,c);
                if((c[THRESH] <= throsh) || (throsh < 0.)) {
                        xweight += c[RMSAMP];
                        sum += (c[PITCH] * c[RMSAMP]);
                }
        }
        return(sum/xweight);
}

double dataset(p,n_args)
/* p1=dataset name, p2=npoles */
float *p;
int n_args;
{
        char *name;
        int i;

        fprec=22;
        if(n_args>1) {
                npoles=p[1];
                npolem1=npoles-1;
                framsize=npoles+4;
                recsize=fprec*framsize;
                bprec=recsize*FLOAT;
                bpframe=framsize*FLOAT;
        }
        lpcinit();
        i=(int)p[0];
        name=(char *)i;
        if(strcmp(name,dataset_name)== 0) {
                printf("\n%s is already open.\n",name);
                return;
        }
        strcpy(dataset_name,name);
        if((anal = open(name,0)) <= 0) {
                printf("Can't open %s\n",name);
                closesf();
        }
}

double lpcstuff(p,n_args)
/* p0=thresh, p1=random amp, p2=unvoiced rate p3= rise, p4= dec, p5=thresh cutof*/
float *p;
int n_args;
{
        risetime=.01; decaytime=.1;
        if(n_args>0) thresh=p[0];
        if(n_args>1) randamp=p[1];
        if(n_args>2) unvoiced_rate=p[2];
        if(n_args>3) risetime=p[3];
        if(n_args>4) decaytime=p[4];
        if(n_args>5) cutoff = p[5]; else cutoff = 0;
        printf("\nAdjusting settings for %s.\n",dataset_name); 
        printf(" --------------------------------------- \n");
        printf("Thresh: %f     Randamp: %f\n",thresh,randamp);
        if(unvoiced_rate == 1)
                printf("Unvoiced frames played at normal rate.\n\n");
        else
                printf("Unvoiced frames played at same rate as voiced 'uns.\n\n");
}

lpcinit()
{
        recsize=framsize*fprec;
        bprec=recsize*FLOAT;
        bpframe=framsize*FLOAT;
}

/* block version of rrand */
/* a modification of unix rand() to return floating point values between
   + and - 1. */


sbrrand(x)
unsigned x;
{
        randx = x;
}
brrand(am,a,j)
float am,*a;
{
        int k;
        for(k=0; k<j; k++) {
                int i = ((randx = randx*1103515245 + 12345)>>16) & 077777;
                *a++ = (float)(i/16384. - 1.) * am;
        }
}

double freset(p,n_args)
float *p;
{
        perperiod = p[0];
        printf(" frame reinitialization reset to %f times per period\n",perperiod);
}

int NBYTES = 32768; profile()
{
	float p[9];
	UG_INTRO("lpcplay",lpcplay);
	UG_INTRO("lpcstuff",lpcstuff);
	UG_INTRO("dataset",dataset);
	UG_INTRO("freset",freset);
	UG_INTRO("mp",mp);
	UG_INTRO("mpset",mpset);
	UG_INTRO("setdev",setdev);
	UG_INTRO("lpcin",lpcin);
	p[0]=1; p[1]=10; p[2]=1024; p[3]=1;
	makegen(p,4);  /* store sinewave in array 1 */
	p[0]=2; p[1]=7; p[2]=512; p[3]=0; p[4]=512; p[5]=1; 
	makegen(p,6);
	maxdev=0;
}
double setdev(p,n_args)
float *p;
{
        maxdev = p[0];
}

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