Code was shared previously on a github, but here's the offending article, and 
the link.

The botherer is called mbc_lpc~.c

edkellytista9/LPCToolkitPd


| 
| 
| 
|  |  |

 |

 |
| 
|  | 
edkellytista9/LPCToolkitPd

LPCToolkitPd - Mark Cartwright's LPC Toolkit for Pure Data
 |

 |

 |





_-_-_-_-_-_-_-^-_-_-_-_-_-_-_

For Lone Shark releases, Pure Data software and published Research, go to 
http://sharktracks.co.uk  

    On Friday, 20 April 2018, 22:02:16 GMT+1, IOhannes m zmölnig 
<zmoel...@iem.at> wrote:  
 
 On 04/20/2018 04:38 PM, Ed Kelly via Pd-list wrote:
> Apologies - I'm trying to do this while buying a house...I don't know if that 
> is simple in Austria but it isn't here.

good luck.
i'm sure it is a hell of stuff to do.

> After reading your email I assumed it was something new, but of course I had 
> just copied, pasted and altered code from a previous external (and forgot> 
> Perhaps it's to do with linking to libm, so I'll check the makefile
once I'm back in a reasonably stable (time-wise) environment.

in the meantime, you could also share your code with us.

> BUT - I've never really understood (in ~13 years of external development) 
> what all those args to class_new() did before, and you've forced me to look 
> deeper into m_pd.h

fwiw, each and every argument to class_new() is covered by the externals
howto.

> I should thank you for that - and yes, I learned how to write externals by 
> reading your howto, in 2005 I believe.

:-)


gdsamr
IOhannes
_______________________________________________
Pd-list@lists.iem.at mailing list
UNSUBSCRIBE and account-management -> 
https://lists.puredata.info/listinfo/pd-list
  
/*
 *   LPC Toolkit
 *   By Mark Cartwright
 *   Pure Data port by Edward Kelly 2018
 *   BSD licence
 *
 *
 */

#include "m_pd.h"
#include <math.h>
//#include <gsl/gsl_vector_float.h>
//#include <gsl/gsl_blas.h>

#ifdef _WIN32
# include <malloc.h> /* MSVC or mingw on windows */
#elif defined(__linux__) || defined(__APPLE__)
# include <alloca.h> /* linux, mac, mingw, cygwin */
#else
# include <stdlib.h> /* BSDs for example */
#endif

static t_class *mbc_lpc_class;

#define MAX_ORDER 200
#define NLOG2(x) (ceil(log2(x)))
#define POW2(x) (1 << x)
#define TWOPI M_PI * 2
#define DEFAULT_FS 44100
#define DEFAULT_FRAMERATE 100
#define DEFAULT_V_SIZE 64
#define DEFAULT_ORDER 32

typedef struct _DSPcomplex
{
  //gsl_vector_float* real;
  //gsl_vector_float* imag;
  t_float* fReal;
  t_float* fImag;

} t_DSPcomplex;

//#define REAL(z,i) gsl_vector_float_set(z,2*(i))
//#define IMAG(z,i) gsl_vector_float_setz(z,2*(i)+1)

typedef struct _lpc 
{
  t_object          x_obj;	           // the object itself (t_pxobject in MSP)
  t_float dummy;
  //t_float*          l_frame_buff;	   //input frame buffer
  //gsl_vector_float*          l_frame_buff;	   //input frame buffer
  //t_float*          l_winframe_buff;       //windowed input frame buffer
  //gsl_vector_float*          l_winframe_buff;       //windowed input frame buffer
  //t_float*	    l_outCoeff_buff;       //coefficient signal
  //gsl_vector_float*	    l_outCoeff_buff;       //coefficient signal
  //t_float*	    l_outParcor_buff; 	   //PARCOR coeffs
  //gsl_vector_float*	    l_outParcor_buff; 	   //PARCOR coeffs
  //t_float*          l_outError_buff;	   //error signal
  //gsl_vector_float*          l_outError_buff;	   //error signal
  //t_float*          l_win;	           //analysis window
  //gsl_vector_float*          l_win;	           //analysis window
  //t_float*	    l_R;
  //gsl_vector_float*	    l_R;
  /*-------------- non-GSL versions --------------*/

  t_float*  frameBuffer;
  t_float*  winFrameBuffer;
  t_float*  outCoeffBuffer;
  t_float*  parcorBuffer;
  t_float*  errorSigBuffer;
  t_float*  window;
  t_float*  lR;
  //  t_float*  vectorBuffer;
  
  double*	    l_W;
  double*	    l_E;
  double*	    l_K;
  double 	    l_G;
  double**	    l_A;
  double 	    l_x1;                  //last samples of pre-emphasis filter
  float 	    l_b1;	           //pre-emph coefficient
  int 	            l_order;	           //predictor order
  int 	            l_order_max;           //max order according to fs = order * frame_rate
  int 	            l_preemph;             //pre-epmhasis filter on/off
  int 	            l_frame_rate;          //analysis frame rate
  int 	            l_frame_size;          //analysis frame size, where fs = frame_rate * frame_size * 2
  int 	            l_hop_size;            //hop_size = frame_size * 2 (b/c of overlap)
  int 	            l_inframe_idx;         //current inframe buffer index
  int 	            l_outframe_idx;	   //current outframe buffer index
  long 	            l_v_size;	           //vector size
  float 	    l_fs;                  //sampling rate
  int 	            l_maxnfft;             //fft length
  int 	            l_log2nfft;	           //log2(fft length)
  int initOrder, initFramerate, initPreemph; // initialization values
  int j;

  //  FFTSetup          l_fftsetup;            //FFTSetup for vDSP FFT functions
  t_DSPcomplex      split;
  //  DSPSplitComplex   l_fftSplitTemp;        //temp split complex vector structure
} t_lpc;

t_int *lpc_perform(t_int *w) 
{
  t_lpc   *x          = (t_lpc *)  (w[1]);
  t_float *in         = (t_float *)(w[2]);
  t_float *out_error  = (t_float *)(w[3]);
  t_float *out_gain   = (t_float *)(w[4]);
  t_float *out_coeff  = (t_float *)(w[5]);
  t_float *out_parcor = (t_float *)(w[6]);
  t_float *out_index  = (t_float *)(w[7]);
  int n               = (int)      (w[8]);
  int p = x->l_order;
  int length = x->l_frame_size;
  int log2nfft = NLOG2(length+p+1);
  int nfft = POW2(log2nfft);
  int nfftO2 = nfft/2;
  t_float recipn = 1.0/nfft;
  int inframeidx = x->l_inframe_idx;
  int outframeidx = x->l_outframe_idx;
  
  int i, j, i1, ji;
  int in_idx = 0, out_idx = 0;
  double val;
  t_float scale, rCorr, re, im;
  //gsl_vector_float *vectorBuffer;
  //vectorBuffer = gsl_vector_float_calloc(MAX_ORDER);	   //input frame buffer
  //x->vectorBuffer = (t_float *) getzbytes( nfftO2 * sizeof(t_float));
  
  if (x->l_preemph)
    {
      while (n--) 
	{
	  val = in[in_idx];
	  in[in_idx] = val + x->l_b1 * x->l_x1;
	  x->l_x1 = val;
	  in_idx++;
	}
      n = (int)(w[8]);
      in_idx = 0;
    }
  
  while (n--) 
    {
      if (inframeidx < length) {
	//copy input into frame buff
	//also copy into winframe buff since GSL puts the result into one of the arg vectors

	//gsl_vector_float_set(&x->l_frame_buff,inframeidx,in[in_idx]);// = x->l_frame_buff[inframeidx] = in[in_idx];
	x->frameBuffer[inframeidx] = in[in_idx];
	
	out_gain[out_idx] = x->l_G;

	//out_error[out_idx] = gsl_vector_float_get(&x->l_outError_buff,outframeidx); //for now
	out_error[out_idx] = x->errorSigBuffer[outframeidx];
	
	if (outframeidx < x->l_order) {

	  //out_coeff[out_idx] = gsl_vector_float_get(&x->l_outCoeff_buff,outframeidx);
	  out_coeff[out_idx] = x->outCoeffBuffer[outframeidx];
	  
	  //out_parcor[out_idx] = gsl_vector_float_get(&x->l_outParcor_buff,outframeidx);
	  out_parcor[out_idx] = x->parcorBuffer[outframeidx];

	  out_index[out_idx] = outframeidx + 1;
	} else {
	  out_coeff[out_idx] = 0.0;
	  out_parcor[out_idx] = 0.0;
	  out_index[out_idx] = 0;
	}
	
	inframeidx++;
	in_idx++;
	outframeidx++;
	out_idx++;
      } else {

	//gsl_vector_float_memcpy(&x->l_winframe_buff,&x->l_frame_buff);
	//memcpy(&x->winFrameBuffer,&x->frameBuffer,x->l_maxnfft * sizeof(t_float));
	x->winFrameBuffer = copybytes(x->frameBuffer, x->l_maxnfft * sizeof(t_float));
	//perform durbin-levinson - for right now, just count to the order---------------
	//clear memory, is this necessary?
	for (i=0; i < p+1; i++){
	  x->lR[i] = 0.0;
	  x->l_W[i] = 0.0;
	  x->l_E[i] = 0.0;
	  x->l_K[i] = 0.0;			
	}
	for(i=0; i<=p; i++) {
	  for(j=0; j < p; j++) x->l_A[i][j] = 0.0;
	}
	//window frame buff
	//vDSP_vmul(x->l_frame_buff, 1, x->l_win, 1, x->l_winframe_buff, 1, length);
	//gsl_vector_float_mul(&x->l_winframe_buff,&x->l_win);
	for(i=0;i<x->l_maxnfft;i++)
	  {
	    x->winFrameBuffer[i] = x->winFrameBuffer[i] * x->window[i];
	  }

#ifdef DEBUG
	for(i=0;i<length;i++)post("\nwinframe(%d) = %g;",i+1,x->winFrameBuffer[i]);
#endif
	
	//create r from auto correlation
	if ((2*nfft*log2(nfft)+nfft) > length*p) { //NOTE: change this to update only when order is changed!
	  //time domain method
	  //for(i=0; i < p+1; i++) vDSP_dotpr(x->l_winframe_buff,1,x->l_winframe_buff+i,1,x->l_R+i,length-i);
	  //gsl_vector_float_memcpy(vectorBuffer,&x->l_winframe_buff);
	  for(i=0; i < p+1; i++)
	    {
	      //gsl_blas_sdot(&x->l_winframe_buff,&x->l_winframe_buff+i,&rCorr);
	      //gsl_vector_float_set(&x->l_R,i,rCorr);
	      for(x->j=0;x->j < length - i; x->j++) x->lR[i] = x->winFrameBuffer[j] * x->winFrameBuffer[j+i];
	    }
	} else {
	  //frequency domain method
	  // zero pad
	  //vDSP_vclr(x->l_winframe_buff+length,1,nfft-length);
	  for(i=length;i<nfft;i++)
	    {
	      //gsl_vector_float_set(&x->l_winframe_buff,i,0);
	      x->winFrameBuffer[i] = 0.0;
	    }
	  for(i=0;i<nfftO2;i++)
	  {
	    x->split.fReal[i] = x->winFrameBuffer[i*2];
	    x->split.fImag[i] = x->winFrameBuffer[i*2+1];
	      //convert to split complex vector
	      //gsl_vector_float_set(&x->split.real,i,gsl_vector_float_get(x->l_winframe_buff,i*2));
	      //gsl_vector_float_set(&x->split.imag,i,gsl_vector_float_get(x->l_winframe_buff,i*2+1));
	  }
	  //vDSP_ctoz( ( DSPComplex * ) x->l_winframe_buff, 2, &x->l_fftSplitTemp, 1, nfftO2);
	  //perform forward in place fft
	  //gsl_fft_complex_radix2_forward(&x->l_winframe_buff,1,nfft);
	  //EXTERN void mayer_fft(int n, t_sample *real, t_sample *imag);
	  //EXTERN void mayer_ifft(int n, t_sample *real, t_sample *imag);
	  mayer_fft(nfftO2,x->split.fReal,x->split.fImag);
	  //vDSP_fft_zrip(x->l_fftsetup, &x->l_fftSplitTemp, 1, log2nfft, FFT_FORWARD);
	  //scaling
	  scale = 0.5;

	  // Ed Kelly: scale real and imaginary parts and calculate magnitudes squared
	  for(i=0;i<nfftO2;i++)
	    {
	      j = i*2;
	      
	      //re = gsl_vector_float_get(&x->l_winframe_buff,j);
	      re = x->split.fReal[j];
	      //im = gsl_vector_float_get(&x->l_winframe_buff,j+1);
	      im = x->split.fImag[j];
	      re *= scale;
	      re = fabs(re * re);
	      im *= scale;
	      im = fabs(im * im);

	      //gsl_vector_float_set(&x->split.real,i,re+im);
	      //gsl_vector_float_set(&x->split.imag,i,0.0);
	      //gsl_vector_float_set(vectorBuffer,j,re+im);
	      x->split.fReal[j] = re+im;
	    }

	  //vDSP_vsmul(x->l_fftSplitTemp.realp,1,&scale,x->l_fftSplitTemp.realp,1,nfftO2);
	  //vDSP_vsmul(x->l_fftSplitTemp.imagp,1,&scale,x->l_fftSplitTemp.imagp,1,nfftO2);
	  //compute PSD
	  //vDSP_zvmags(&x->l_fftSplitTemp,1,x->l_fftSplitTemp.realp,1,nfftO2);

	  //clear imaginary part
	  for(i=0;i<nfftO2;i++)
	  {
	      //IMAG(&x->l_winframe_buff,i) = 0.0;
	      //gsl_vector_float_set(&x->l_winframe_buff,i*2+1,0.0);
	    x->split.fImag[i] = 0;
	  }
	  //vDSP_vclr(x->l_fftSplitTemp.imagp,1,nfftO2);
	  //perform inverse in place fft
	  //gsl_fft_complex_radix2_backward(vectorBuffer,1,nfft);
	  //vDSP_fft_zrip(x->l_fftsetup, &x->l_fftSplitTemp, 1, log2nfft, FFT_INVERSE);

	  mayer_ifft(nfftO2,x->split.fReal,x->split.fImag);
	  
	  //scaling
	  //vDSP_vsmul(x->l_fftSplitTemp.realp,1,&recipn,x->l_fftSplitTemp.realp,1,nfftO2);
	  //vDSP_vsmul(x->l_fftSplitTemp.imagp,1,&recipn,x->l_fftSplitTemp.imagp,1,nfftO2);
	  //gsl_vector_float_scale(vectorBuffer,&recipn);

	  for(i=0;i<nfftO2;i++)
	    {
	      x->lR[i*2] = x->split.fReal[i] * recipn;
	      x->lR[i*2+1] = x->split.fImag[i] * recipn;
	    }
	  
	  //convert back to real number vector
	  //vDSP_ztoc(&x->l_fftSplitTemp, 1, (DSPComplex *)x->l_R, 2, nfftO2);
	  //gsl_vector_float_memcpy(x->l_R,vectorBuffer);
	}
	
	
	/*for(i=0; i < p+1; i++) {
	  x->l_R[i] = 0.0;
	  for(j=0; j < length - i; j++) {
	  x->l_R[i] += x->l_winframe_buff[j] * x->l_winframe_buff[i+j];
	  //x->l_R[i] += x->l_win[j] * x->l_win[i+j];
	  }
	  }*/
#ifdef DEBUG
	for(i=0;i< p+1; i++) post("\nR(%d) = %f;",i+1,x->lR[i]);
#endif
	
	//x->l_W[0] = gsl_vector_float_get(x->l_R,1);
	//x->l_E[0] = gsl_vector_float_get(x->l_R,0);
	x->l_W[0] = x->lR[1];
	x->l_E[0] = x->lR[0];
	
	for (i = 1; i <= p; i++) {
	  x->l_K[i] = x->l_W[i-1] / x->l_E[i-1];
	  
	  x->l_A[i][i] = x->l_K[i];
	  i1 = i - 1;
	  if (i1 >= 1) {
	    for (j = 1; j <=i1; j++) {
	      ji = i - j;
	      x->l_A[j][i] = x->l_A[j][i1] - x->l_K[i] * x->l_A[ji][i1];
	    }				
	  }
	  
	  x->l_E[i] = x->l_E[i-1] * (1.0 - x->l_K[i] * x->l_K[i]);
	  
	  if (i != p) {
	    x->l_W[i] = x->lR[i+1];
	    for (j = 1; j <= i; j++) {
	      x->l_W[i] -= x->l_A[j][i] * x->lR[i-j+1];
	    }
	  }
	}
	
	x->l_G = sqrt(x->l_E[p]);
	for (i=0; i < p; i++) {
	  x->outCoeffBuffer[i] = (t_float)(x->l_A[i+1][p]);
	  x->parcorBuffer[i] = (t_float)(x->l_K[i+1]);
	  //#ifdef DEBUG
	  //post("\nParcor(%d) = %g;",i+1,x->l_K[i+1]);
	  //post("\nCoeff(%d) = %g;",i+1,x->l_A[i+1][p]);
	  //#endif
	}
	
	//--------------------------------------------------------------------------------
	
	//copy right side to left side, move delayed input to output
	for (i=0; i < x->l_hop_size; i++) {
	  x->errorSigBuffer[i] = x->frameBuffer[i];
	  x->frameBuffer[i] = x->frameBuffer[i + x->l_hop_size];
	}
	
	inframeidx = x->l_hop_size;
	outframeidx = 0;
	n++; //to avoid skipping a sample (since we already decremented
	while (n--) {
	  x->frameBuffer[inframeidx] = in[in_idx];
				
	  out_gain[out_idx] = (t_float)(x->l_G);
	  out_error[out_idx] = x->errorSigBuffer[outframeidx]; //for now
	  if (outframeidx < x->l_order) {
	    out_coeff[out_idx] = x->outCoeffBuffer[outframeidx];
	    out_parcor[out_idx] = x->parcorBuffer[outframeidx];
	    out_index[out_idx] = (t_float)(outframeidx + 1);
	  } else {
	    out_coeff[out_idx] = 0.0;
	    out_parcor[out_idx] = 0.0;
	    out_index[out_idx] = 0;
	  }
	  
	  inframeidx++;
	  in_idx++;
	  outframeidx++;
	  out_idx++;
	}
	break;
      }
    }
  
  x->l_inframe_idx = inframeidx;
  x->l_outframe_idx = outframeidx;
  
  return (w+9);
}

void lpc_hanning(t_lpc *x)
{
  t_float N = (t_float)x->l_frame_size;
  int n;
	
  for (n=0; n<(int)N; n++)
    {
      x->window[n] = 0.5 * (1.0 - cos((TWOPI*((t_float)n+1))/(N+1)));
    }
  post("Generating Hanning window for LPC analysis");  
}

void lpc_hamming(t_lpc *x)
{
  t_float N = (t_float)x->l_frame_size;
  int n;
	
  for (n=0; n<(int)N; n++)
    {
      x->window[n] = (0.54 - 0.46*cos((TWOPI*(t_float)n)/(N-1)));
    }
  post("Generating Hamming window for LPC analysis");
}

void lpc_bartlett(t_lpc *x)
{
  t_float N = (t_float)x->l_frame_size;
  int n;

  for (n=0; n<(int)N; n++)
    {
      x->window[n] = 2.0/(N - 1) * ((N-1)/2 - fabs((t_float)n - (N-1)/2.0));
    }
  post("Generating Bartlett window for LPC analysis");
}

void lpc_preemph(t_lpc *x, t_floatarg n)
{
  x->l_preemph = n != 0 ? 1 : 0;
}

void lpc_init(t_lpc *x) {
	int i;
	
	if (x->l_fs < (t_float)x->l_frame_rate * (t_float)x->l_order) {
	  x->l_frame_rate = (long)(x->l_fs / (t_float)x->l_order);
		error("mbc.lpc~: framerate * order must be less than or equal to sampling rate.  framerate has been changed to %d", x->l_frame_rate);
	}
	
	x->l_hop_size = (int)(x->l_fs / (t_float)x->l_frame_rate);
	
	if (x->l_v_size > x->l_hop_size) {
		error("mbc.lpc~: warning: frame_size is less than vector size.  this may cause errors, please reduce the frame rate or increase the vector size");
	}
	
	x->l_order_max = x->l_fs / (t_float)x->l_frame_rate;
	x->l_frame_size = x->l_hop_size * 2;
	x->l_inframe_idx = x->l_hop_size;
	x->l_outframe_idx = 0;
	x->l_log2nfft = (int) NLOG2(x->l_frame_size+MAX_ORDER+1);
	x->l_maxnfft = POW2(x->l_log2nfft);
	
	// free memory if needed
	lpc_free_arrays(x);
	
	//allocate memory
	//x->l_frame_buff = (t_float *) getzbytes( x->l_frame_size * sizeof(t_float));
	//x->l_frame_buff = gsl_vector_float_calloc(x->l_frame_size);
	x->frameBuffer = (t_float *) getzbytes( x->l_frame_size * sizeof(t_float));
	x->winFrameBuffer = (t_float *) getzbytes( x->l_maxnfft * sizeof(t_float));
	x->outCoeffBuffer = (t_float *) getzbytes(MAX_ORDER * sizeof(t_float));
	x->parcorBuffer = (t_float *) getzbytes(MAX_ORDER * sizeof(t_float));
	x->errorSigBuffer = (t_float *) getzbytes( x->l_hop_size * sizeof(t_float));
	x->window = (t_float *) getzbytes( x->l_frame_size * sizeof(t_float));
	x->lR = (t_float *) getzbytes( x->l_maxnfft * sizeof(t_float));
	x->l_W = (double *) getzbytes( (MAX_ORDER + 1) * sizeof(double));
	x->l_E = (double *) getzbytes( (MAX_ORDER + 1) * sizeof(double));
	x->l_K = (double *) getzbytes( (MAX_ORDER + 1) * sizeof(double));
	x->l_A = (double **) getzbytes( (MAX_ORDER + 1) * sizeof(double*));
	for(i=0; i<MAX_ORDER; i++) {
		x->l_A[i] = (double *)getzbytes( (MAX_ORDER + 1) * sizeof(double));
	}
	x->split.fReal = (float *)getzbytes( (x->l_maxnfft / 2) * sizeof(float));
	x->split.fImag = (float *)getzbytes( (x->l_maxnfft / 2) * sizeof(float));
		
	x->l_x1 = 0;
	x->l_G = 0.0;
	
	x->l_b1 = -0.98;
	
	//calculate window
	lpc_hamming(x);
	//create FFTsetups
	//x->l_fftsetup = vDSP_create_fftsetup(x->l_log2nfft,FFT_RADIX2);
	//if (!x->l_fftsetup) error("mbc.lpc~: not enough available memory");
	
}

void lpc_order(t_lpc *x, t_floatarg n)
{
  if (x->l_order_max < (int)n)
    {
      error("mbc.lpc~: framerate * order must be less than or equal to sampling rate.  At the current setting maxorder is %d.  For a higher order, lower the framerate.", x->l_order_max);
      x->l_order = x->l_order_max;
    }
  else
    {
      x->l_order = (int)n > 4 ? (int)n : 4;
    }
  x->l_frame_rate = x->l_fs / x->l_order;
  lpc_init(x);  
    //lpc_init(x) ?
}

void lpc_free_arrays(t_lpc *x)
{
  //int i;
	
  /*gsl_vector_float_free(x->l_frame_buff);
  x->l_frame_buff = NULL;
  gsl_vector_float_free(x->l_winframe_buff);
  x->l_winframe_buff = NULL;
  gsl_vector_float_free(x->l_outCoeff_buff);
  x->l_outCoeff_buff = NULL;
  gsl_vector_float_free(x->l_outError_buff);
  x->l_outError_buff = NULL;
  gsl_vector_float_free(x->l_outParcor_buff);
  x->l_outParcor_buff = NULL;
  gsl_vector_float_free(x->l_win);
  x->l_win = NULL;
  gsl_vector_float_free(x->l_R);
  x->l_R = NULL;*/
  //x->frameBuffer = (t_float *) getzbytes( x->l_frame_size * sizeof(t_float));
  //	x->winFrameBuffer = (t_float *) getzbytes( x->l_maxnfft * sizeof(t_float));
  //	x->OutCoeffBuffer = (t_float *) getzbytes(MAX_ORDER * sizeof(t_float));
  //	x->parcorBuffer = (t_float *) getzbytes(MAX_ORDER * sizeof(t_float));
  //	x->errorSigBuffer = (t_float *) getzbytes( x->l_hop_size * sizeof(t_float));
  //	x->window = (t_float *) getzbytes( x->l_frame_size * sizeof(t_float));
  freebytes(x->frameBuffer, x->l_frame_size * sizeof(t_float));
  freebytes(x->winFrameBuffer, x->l_maxnfft * sizeof(t_float));
  freebytes(x->outCoeffBuffer, MAX_ORDER * sizeof(t_float));
  freebytes(x->parcorBuffer, MAX_ORDER * sizeof(t_float));
  freebytes(x->errorSigBuffer, x->l_hop_size * sizeof(t_float));
  freebytes(x->window, x->l_frame_size * sizeof(t_float));
  freebytes(x->lR, x->l_maxnfft * sizeof(t_float));
  x->frameBuffer = NULL;
  x->winFrameBuffer = NULL;
  x->outCoeffBuffer = NULL;
  x->parcorBuffer = NULL;
  x->errorSigBuffer = NULL;
  x->window = NULL;
  x->lR = NULL;
  
  if (x->l_W) {
    freebytes(x->l_W, (MAX_ORDER + 1) * sizeof(double));
    x->l_W = NULL;
  }
  if (x->l_E) {
    freebytes(x->l_E, (MAX_ORDER + 1) * sizeof(double));
    x->l_E = NULL;
  }
  if (x->l_K) {
    freebytes(x->l_K, (MAX_ORDER + 1) * sizeof(double));
    x->l_K = NULL;
  }
  if (x->l_A) {		
    freebytes(x->l_A, (MAX_ORDER + 1) * sizeof(double));
    x->l_A = NULL;
  }
  /*	if (x->l_fftSplitTemp.realp) {
	sysmem_freeptr(x->l_fftSplitTemp.realp);
	x->l_fftSplitTemp.realp = NULL;
	}
	if (x->l_fftSplitTemp.imagp) {
	sysmem_freeptr(x->l_fftSplitTemp.imagp);
	x->l_fftSplitTemp.imagp = NULL;
	}
	
	if (x->l_fftsetup) {
	vDSP_destroy_fftsetup(x->l_fftsetup);
	x->l_fftsetup = NULL;
	}*/
  freebytes(x->split.fReal, (x->l_maxnfft / 2) * sizeof(t_float));
  freebytes(x->split.fImag, (x->l_maxnfft / 2) * sizeof(t_float));
  x->split.fReal = NULL;
  x->split.fImag = NULL;
}

void lpc_window(t_lpc *x, t_floatarg f)
{
  if(f == 1) lpc_bartlett(x);
  else if(f == 2) lpc_hanning(x);
  else lpc_hamming(x);
}

void lpc_dsp(t_lpc *x, t_signal **sp)
{
  x->l_fs = sys_getsr();
  if(sp[0]->s_n != x->l_v_size) x->l_v_size = sp[0]->s_n;
  lpc_init(x);
  //  dsp_add(lpc_blit_perform, 4, x,
  //  sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);

  dsp_add(lpc_perform, 8, x, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, sp[4]->s_vec, sp[5]->s_vec, sp[6]->s_vec, sp[0]->s_n);
}

void *lpc_new(int argc, t_atom *argv)
{
  t_lpc *x = (t_lpc *)pd_new(mbc_lpc_class);

  //#define DEFAULT_FS 44100
  //#define DEFAULT_FRAMERATE 100
  //#define DEFAULT_V_SIZE 64
  //#define DEFAULT_ORDER 32
  /*if(argc >= 3)
    {
      x->initOrder = atom_getfloat(argv);
      x->initFramerate = atom_getfloat(argv+1);
      x->initPreemph = atom_getfloat(argv+2);
      }
      else
      if(argc == 2)*/
  if(argc >= 2)
    {
      x->initOrder = atom_getfloat(argv);
      //x->initFramerate = atom_getfloat(argv+1);
      x->initPreemph = atom_getfloat(argv+1);
    }
  else if(argc == 1)
    {
      x->initOrder = atom_getfloat(argv);
      //x->initFramerate = DEFAULT_FRAMERATE;
      x->initPreemph = 0;
    }
  else
    {
      x->initOrder = DEFAULT_ORDER;
      //x->initFramerate = DEFAULT_FRAMERATE;
      x->initPreemph = 0;
    }
      
  if(x->initOrder < 1)
    {
      post("Order must be from 1 to 200! Setting to %d",DEFAULT_ORDER);
      x->l_order = DEFAULT_ORDER;
    }
  else if(x->initOrder > MAX_ORDER)
    {
      post("Order cannot be greater than %d!",MAX_ORDER);
      x->l_order = MAX_ORDER;
    }
  else
    {
      post("Setting order to %d",x->initOrder);
      x->l_order = x->initOrder;
    }
  x->l_fs = sys_getsr();
  x->l_frame_rate = (int)(x->l_fs / (t_float)x->l_order);
  lpc_init(x);  
  //int length = x->l_frame_size;
  //int log2nfft = NLOG2(length+p+1);
  //int nfft = POW2(log2nfft);
  //int nfftO2 = nfft/2;
    //MAX_ORDER is wrong - check fft size calculation!
  /*  x->l_frame_buff = gsl_vector_float_calloc(MAX_ORDER);	   //input frame buffer
  x->l_winframe_buff = gsl_vector_float_calloc(MAX_ORDER);       //windowed input frame buffer
  x->l_outCoeff_buff = gsl_vector_float_calloc(MAX_ORDER);       //coefficient signal
  x->l_outParcor_buff = gsl_vector_float_calloc(MAX_ORDER); 	   //PARCOR coeffs
  x->l_outError_buff = gsl_vector_float_calloc(MAX_ORDER);	   //error signal
  x->l_win = gsl_vector_float_calloc(MAX_ORDER);	           //analysis window
  */
  inlet_new (&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal);
  //floatinlet_new (&x->x_obj, &x->f_win);
  outlet_new(&x->x_obj, &s_signal);
  outlet_new(&x->x_obj, &s_signal);
}

void lpc_setup(void)
{
  mbc_lpc_class = class_new(gensym("mbc_lpc~"), 
  (t_newmethod)lpc_new, 
  0, sizeof(t_lpc),
  CLASS_DEFAULT, A_DEFFLOAT, 0);

  post("->mbc_lpc~");
  post("->by Mark Cartwright");
  post("->Pd port by Edward Kelly");
  post("->2018");

  class_addmethod(mbc_lpc_class,
  (t_method)lpc_dsp, gensym("dsp"), 0);
  CLASS_MAINSIGNALIN(mbc_lpc_class, t_lpc, dummy);
  class_addmethod(mbc_lpc_class, (t_method)lpc_order, gensym("order"), A_DEFFLOAT, 12);
  class_addmethod(mbc_lpc_class, (t_method)lpc_preemph, gensym("preemph"), A_DEFFLOAT, 0);
}
_______________________________________________
Pd-list@lists.iem.at mailing list
UNSUBSCRIBE and account-management -> 
https://lists.puredata.info/listinfo/pd-list

Reply via email to