ftp.nice.ch/pub/next/unix/developer/_VoiceClass.s/VoiceClass/LPC/fitlpc/fitlpc.c

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

/*  fitlpc routine by Perry R. Cook
			Stanford CCRMA 1991.
	This performs linear predictive coding
	to a file.  Read lpcInstructions for 
	details.
*/ 

#import <stdio.h>
#import <fcntl.h>
#import <string.h>
#import <math.h>

#define MAX_BLOCK 4096
#define MAX_ORDER 100

float autocorr(int size,float *data,float *result)
{
    int i,j,k;
    float temp,norm;
    for (i=0;i<size/2;i++)	{
        result[i] = 0.0;
	for (j=0;j<size-i-1;j++)	{
	    result[i] += data[i+j] * data[j];
	}
    }
    temp = result[0];
    j = size*0.02;
    while (result[j]<temp && j < size/2)	{
	temp = result[j];
        j += 1;
    }
    temp = 0.0;
    for (i=j;i<size*0.5;i++) {
        if (result[i]>temp) {
	    j = i;
	    temp = result[i];
	}
    }
    norm = 1.0 / size;
    k = size/2;
    for (i=0;i<size/2;i++) result[i] *=  (k - i) * norm;
    if ((result[j] / result[0]) < 0.4) j = 0;
    if (j > size/4) j = 0;
    return (float) j;
}

int minvert(int size,float mat[][MAX_ORDER])
{
    int item,row,col,rank,t2;
    float temp,res[MAX_ORDER][MAX_ORDER];
    int ok,zerorow;
        
    for (row=1;row<=size;row++)	    {
        for (col=1;col<=size;col++)	{
	    //    fprintf(stdout," %f ",mat[row][col]);
	    if (row==col) 
	        res[row][col] = 1.0;
	    else
	        res[row][col] = 0.0;
	}
	//    fprintf(stdout,"\n");
    }
    for (item=1;item<=size;item++) {
        if (mat[item][item]==0)		{
            for (row=item;row<=size;row++)   {
    		for (col=1;col<=size;col++)	{
    		    mat[item][col] = mat[item][col] + mat[row][col];
    		    res[item][col] = res[item][col] + res[row][col];
		}
	    }
	} 
	for (row=item;row<=size;row++)  {
	    temp=mat[row][item];
	    if (temp!=0)	{
		for (col=1;col<=size;col++)	{
		    mat[row][col] = mat[row][col] / temp;
		    res[row][col] = res[row][col] / temp;
		}
	    } 
	}
	if (item!=size)	{
	    for (row=item+1;row<=size;row++)	{
		temp=mat[row][item];
		if (temp!=0)	{
		    for (col=1;col<=size;col++)	{
			mat[row][col] = mat[row][col] - mat[item][col];
			res[row][col] = res[row][col] - res[item][col];
		    }
		} 
	    }
	} 
    }
    for (item=2;item<=size;item++)   {
        for (row=1;row<item;row++)	{
    	    temp = mat[row][item];
	    for (col=1;col<=size;col++)	   {
		mat[row][col] = mat[row][col] - temp * mat[item][col];
		res[row][col] = res[row][col] - temp * res[item][col];
	    }
	}
    }
/*    ok = TRUE;
    rank = 0;
    for (row=1;row<=size;row++)	{
	zerorow = TRUE;
	for (col=1;col<=size;col++)	{
	    if (mat[row][col]!=0) zerorow = FALSE;
	    t2 = (mat[row][col] + 0.5);
	    if (row==col&&t2!=1) ok = FALSE;
	    t2 = fabs(mat[row][col]*100.0);
	    if (row!=col&&t2!=0) ok = FALSE;
	}
	if (!zerorow) rank += 1;
    }
    if (!ok)	{
        fprintf(stdout,"Matrix Not Invertible\n");
        fprintf(stdout,"Rank is Only %i of %i\n",rank,size);
    }									*/
    for (row=1;row<=size;row++)	{
        for (col=1;col<=size;col++)	{
	    mat[row][col] = res[row][col];
	}
    }	
    return rank;
}

float lpc_from_data(int order, int size, float *data, float *coeffs)
{
    float r_mat[MAX_ORDER][MAX_ORDER];
    int i,j;
    float pitch;
    float corr[MAX_BLOCK];

    pitch = autocorr(size, data,corr);
    for (i=1;i<order;i++) {
	for (j=1;j<order;j++) r_mat[i][j] = corr[abs(i-j)];
    }
    minvert(order-1,r_mat);
    for (i=0;i<order-1;i++)	{
        coeffs[i] = 0.0;
	for (j=0;j<order-1;j++)	{
	    coeffs[i] += r_mat[i+1][j+1] * corr[1+j];
	}
    }
    return pitch;
}

float predict(int order,int hop_size,float *data,float *coeffs, int resFile)
{
    int i,j,n_write;
    float power=0.0,error,tmp;
    float Zs[MAX_ORDER];
    for (i=0;i<order;i++) Zs[i] = data[order-i-1];
    for (i=order;i<=hop_size+order;i++)	{
        tmp = 0.0;
	for (j=0;j<order;j++)  tmp += Zs[j]*coeffs[j];
	for (j=order-1;j>0;j--) Zs[j] = Zs[j-1];
	Zs[0] = data[i];
//    }
//    for (i=0;i<hop_size;i++)	{
//        tmp = coeffs[0] + data[i+order-1];
//	for (j=1;j<order;j++) tmp += coeffs[j] * data[i+order-1-j];
	error = data[i] - tmp;
	n_write = write(resFile,&error,4);
	power += error * error;
    }
    return sqrt(power) / hop_size; 	
}

int check_stable(int order,float *coeffs)
{
    int i,j;
    float output,Zs[MAX_ORDER];
    for (i=0;i<order;i++) Zs[i] = 0.0;
    Zs[0] = 1.0;
    for (i=0;i<2*order;i++)	{
        output = 0.0;
	for (j=0;j<order;j++)  output += Zs[j]*coeffs[j];
	for (j=order-1;j>0;j--) Zs[j] = Zs[j-1];
	Zs[0] = output;
    }
    j = 1;
    if (output>1.0) j = 0;
    return j; 	
}

main(ac,av) 
    int ac;
    char *av[]; 
{
    char *file_name_in,*file_name_out,residual_file[200];
    float data[MAX_BLOCK],out_data[MAX_ORDER];
    int fd,fd2,fdr,n_read,n_write;
    int i,time=0,block_size,hop_size,order;
    float pitch,power;
    
    if (ac==6)	{
	order = atoi(av[1]);
	block_size = atoi(av[2]);
	hop_size = atoi(av[3]);
	if (hop_size>block_size)	{
	    hop_size = block_size - order;
	    fprintf(stderr,"Setting hop size to block size - order.\n");
	}
	file_name_in = av[4];
         file_name_out = av[5];
         fd = open(file_name_in,0);
	if (fd!=-1) 	{
	  if (!strcmp(file_name_in,file_name_out))	{
		fprintf(stderr,"Input and output files can't have same name!!\n");
		exit(0);
	   }
	   fd2 = creat(file_name_out, 0666);
	   n_write = write(fd2,&order,4);
	   n_write = write(fd2,&hop_size,4);
	   n_read = read(fd,data,block_size*4);
	   n_read = 10000;
	   strcpy(residual_file,file_name_in);
	   strcat(residual_file,".residual");
	   fdr = creat(residual_file, 0666);
	   while (n_read>0)	{
	       pitch = lpc_from_data(order+1,block_size,data,out_data);
	       if (!check_stable(order,out_data))	{ 
	           fprintf(stderr,"This set is not stable!!\n");
//		   stabilize(order,out_data);
	       }
	       power = predict(order,hop_size,data,out_data,fdr);
	       time+= hop_size;
	       printf("%i   %f   %f\n",time,pitch,power);
	       for (i=0;i<block_size-hop_size;i++) data[i] = data[hop_size+i];
	       n_read = read(fd,&data[block_size-hop_size],hop_size*4);
	       n_write = write(fd2,&pitch,4);
	       n_write = write(fd2,&power,4);
	       n_write = write(fd2,&out_data,order*4);
	   }
	   close(fd);
	   close(fd2);
         }
        else
    	    printf("I couldn't find your input file!!!\n");
    }
    else
    	printf("Format is fitlpc order blocksize hopsize infile outfile.lpc\n");
    return;
}

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