Forums > Dev

external lpc~ : syntax problem

May 23, 2013 | 4:12 am

Hi everyone !

I’m trying to port into Max a pd external (which does lpc analysis on a signal, it comes in pd-extended) and I’m having some issues. Here it is :

/*  Linear Predictive Coding – PARCOR and residual generation

*  Copyright (C) 2005 Nicolas Chetry <okin@altern.org>

*  and Edward Kelly <morph_2016@yahoo.co.uk>

*

*  This program is free software; you can redistribute it and/or modify

*  it under the terms of the GNU General Public License as published by

*  the Free Software Foundation; either version 2 of the License, or

*  (at your option) any later version.

*

*  This program is distributed in the hope that it will be useful,

*  but WITHOUT ANY WARRANTY; without even the implied warranty of

*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the

*  GNU General Public License for more details.

*  You should have received a copy of the GNU General Public License

*  along with this program; if not, write to the Free Software

*  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

*/

 

#include "m_pd.h"

#include <math.h>

#define MAXPOLES 100

 

static t_class *lpc_tilde_class;

 

typedef struct _lpc_schur

{

t_float *c_input, *c_residual;

/* just so we don’t get clicks */

t_atom x_last_parcors[MAXPOLES];

t_atom x_parcors[MAXPOLES];

} t_lpc_schur;

 

typedef struct _lpc_tilde

{

t_object x_obj;

t_float f_dummy;

t_float x_order, x_lastorder;

t_outlet *parcor_list;

t_lpc_schur x_schur;

} t_lpc_tilde;

 

t_int *lpc_tilde_perform(t_int *w)

{

t_lpc_tilde     *x =     (t_lpc_tilde *)(w[1]);

t_lpc_schur *schur =     (t_lpc_schur *)(w[2]);

int              n =               (int)(w[3]);

t_float        *in = schur->c_input;

t_float       *res = schur->c_residual;

//  t_float   *parcors = schur->PARCORS;

//  t_float       *acf = schur->ACF;

//  t_float         *k = schur->K;

//  t_float         *p = schur->P;

//  t_float         *r = schur->r;

t_int          ord = (int)x->x_order;

t_int        l_ord = (int)x->x_lastorder;

//  t_float parcors[ord];

float acf[ord+1];

float k[ord+1];

float p[ord+1];

float r[ord+1];

float mem[ord];

int i, j, bid, y, z;

int g, h;

float tmp, temp, sav, di;

float parcor_1;

for (i=0; i<ord; i++)

{

SETFLOAT (&schur->x_parcors[i],0);

mem[i] = 0.0;

}

for (j=0; j<=ord; j++)

{

acf[j] = 0;

for (i=j; i<n; i++)

{

acf[j] += in[i]*in[i-j];

}

}

if (acf[0] == 0)

{

for (i=0; i<ord; i++)

{

SETFLOAT (&schur->x_parcors[i],0);

}

}

for (i=0; i<=ord; i++)

{

p[i]=acf[i];

if (i > 0 && i < ord)

{

k[ord+1-i] = acf[i];

}

}

/* Schurr recursion */

for (y=1; y<=ord; y++)

{

if (p[0] < fabs (p[1]))

{

for (i=y; i<=ord; i++)

{

r[i] = 0;

}

for (bid=1; bid <=ord; bid++)

{

SETFLOAT (&schur->x_parcors[bid-1],r[bid]);

//    x->x_parcors[bid-1] = r[bid];

}

}

r[y] = fabs(p[1])/p[0];

 

if (p[1] >0)

{

r[y] = -1.*r[y];

}

if (y==ord)

{

for (bid=1; bid <=ord; bid++)

{

SETFLOAT (&schur->x_parcors[bid-1],r[bid]);

//    x->x_parcors[bid-1] = r[bid];

}

}

p[0] += p[1]*r[y];

 

for (z=1; z <=ord-y; z++)

{

p[z]        = p[z+1] + k[ord+1-z]*r[y];

k[ord+1-z] += p[z+1] * r[y];

}

}

for (bid=1; bid <=ord; bid++)

{

SETFLOAT (&schur->x_parcors[bid-1],r[bid]);

}

parcor_1 = atom_getfloatarg(0,ord,schur->x_parcors); /* in order to avoid nil coefficients */

if (parcor_1 > 1e-5 || parcor_1 < -1e-5)

{

outlet_list(x->parcor_list,gensym("list"),ord,schur->x_parcors);

 

/* Analysis FIR lattice filtering */

for (g=0; g<n; g++)

{

/* Analysis – Lattice structure */

sav = di = in[g];

for (i=0; i<ord; i++)

{

t_float parcor = atom_getfloatarg (i,ord,schur->x_parcors);

SETFLOAT (&schur->x_last_parcors[i],parcor);

x->x_lastorder = ord;

temp = mem[i] + parcor*di;

di += parcor*mem[i];

mem[i] = sav;

sav = temp;

}

res[g] = di;

}  /* next g */

}

else

{

outlet_list(x->parcor_list,gensym("list"),l_ord,schur->x_last_parcors);

for (g=0; g<n; g++)

{

res[g] = 0;

}

}

return(w+4);

}

 

void *lpc_tilde_dsp(t_lpc_tilde *x, t_signal **sp)

{

x->x_schur.c_input = sp[0]->s_vec;

x->x_schur.c_residual = sp[1]->s_vec;

dsp_add(lpc_tilde_perform, 3, x, &x->x_schur, sp[0]->s_n);

return (void *)x;

}

 

void *lpc_tilde_new(t_floatarg f)

{

t_lpc_tilde *x = (t_lpc_tilde *)pd_new(lpc_tilde_class);

x->x_order = f >= 1 ? (int)f : 5;

floatinlet_new(&x->x_obj,&x->x_order);

outlet_new(&x->x_obj, &s_signal);

x->parcor_list = outlet_new(&x->x_obj, &s_list);

return (void *)x;

}

 

void lpc_tilde_setup(void)

{

lpc_tilde_class = class_new(gensym("lpc~"), (t_newmethod)lpc_tilde_new, 0, sizeof(t_lpc_tilde), CLASS_DEFAULT, A_DEFFLOAT, 0);

 

post("\n. . Linear Predictive Coding. . . . . . . .");

post(". . PARCOR coefficients from input. . . . .");

post(". . by Nicolas Chetry <okin@altern.org> . .");

post(". & Edward Kelly <morph_2016@yahoo.co.uk> .");

class_addmethod(lpc_tilde_class, (t_method)lpc_tilde_dsp, gensym("dsp"), 0);

 

 

CLASS_MAINSIGNALIN(lpc_tilde_class, t_lpc_tilde, f_dummy);

}

 

In the lpc_tile_perform function, there are declarations of arrays of float that take a non-constant integer as argument (like float acf[ord+1]), which cannot be done in C, as far as I know.

This code is given this way in the source, I did not change it. So my question is, is the code correct ? If not, how could I fix it ?

Thanks in advance


May 23, 2013 | 6:55 am

Thanks a lot you for your answer ! I will try these solutions !


Viewing 2 posts - 1 through 2 (of 2 total)