From 73ac4e4c559a0c49995bf8b1921c2b91cce7503c Mon Sep 17 00:00:00 2001 From: Ben Wesch Date: Thu, 17 Oct 2024 21:05:36 +0200 Subject: [PATCH 1/3] preserve signal pointers closes #62 --- pdlua.c | 71 +++++++++++++++++++++++++++++++-------------------------- pdlua.h | 9 ++++++++ 2 files changed, 48 insertions(+), 32 deletions(-) diff --git a/pdlua.c b/pdlua.c index 21450ce..e14edba 100644 --- a/pdlua.c +++ b/pdlua.c @@ -741,6 +741,13 @@ static void pdlua_free( t_pdlua *o /**< The object to destruct. */) lua_pop(__L(), 1); /* pop the global "pd" */ PDLUA_DEBUG("pdlua_free: end. stack top %d", lua_gettop(__L())); + // Free sig_info if it exists + // FIXME: necessary? + if (o->sig_info) { + freebytes(o->sig_info, (o->siginlets + o->sigoutlets) * sizeof(t_pdlua_siginfo)); + o->sig_info = NULL; + } + // Collect garbage // If we don't do this here, it could potentially leak if no other pdlua objects are used afterwards lua_gc(__L(), LUA_GCCOLLECT); @@ -1071,14 +1078,10 @@ static t_int *pdlua_perform(t_int *w){ for (int i = 0; i < o->siginlets; i++) { lua_newtable(__L()); - t_signal *sig = (t_signal *)(w[2 + i]); - t_float *in = sig->s_vec; -#if PD_MULTICHANNEL - int nchans = sig->s_nchans ? sig->s_nchans : 1; -#else - int nchans = 1; -#endif - int s_n_allchans = nblock * nchans; // sum of all inlet samples + t_float *in = o->sig_info[i].vec; + int nchans = o->sig_info[i].nchans; + int s_n_allchans = nblock * nchans; + for (int j = 0; j < s_n_allchans; j++) { lua_pushinteger(__L(), j + 1); @@ -1091,7 +1094,7 @@ static t_int *pdlua_perform(t_int *w){ { mylua_error(__L(), o, "perform"); lua_pop(__L(), 1); /* pop the global pd */ - return w + o->siginlets + o->sigoutlets + 2; + return w + 2; } if (!lua_istable(__L(), -1)) @@ -1109,21 +1112,16 @@ static t_int *pdlua_perform(t_int *w){ } } lua_pop(__L(), 1 + o->sigoutlets); - return w + o->siginlets + o->sigoutlets + 2; + return w + 2; } for (int i = o->sigoutlets - 1; i >= 0; i--) { - t_signal *sig = (t_signal *)(w[2 + o->siginlets + i]); - t_float *out = sig->s_vec; -#if PD_MULTICHANNEL - int nchans = sig->s_nchans ? sig->s_nchans : 1; -#else - int nchans = 1; -#endif - int s_n_allchans = nblock * nchans; // sum of all outlet samples - for (int j = 0; j < s_n_allchans; j++) - { + t_float *out = o->sig_info[o->siginlets + i].vec; + int nchans = o->sig_info[o->siginlets + i].nchans; + int s_n_allchans = nblock * nchans; + + for (int j = 0; j < s_n_allchans; j++) { lua_pushinteger(__L(), (lua_Integer)(j + 1)); lua_gettable(__L(), -2); if (lua_isnumber(__L(), -1)) @@ -1141,14 +1139,14 @@ static t_int *pdlua_perform(t_int *w){ PDLUA_DEBUG("pdlua_perform: end. stack top %d", lua_gettop(__L())); - return w + o->siginlets + o->sigoutlets + 2; + return w + 2; } static void pdlua_dsp(t_pdlua *x, t_signal **sp){ int sum = x->siginlets + x->sigoutlets; if(sum == 0) return; x->sig_warned = 0; - x->blocksize = (int)sp[0]->s_n; // local block size instead of sys_getblksize(); + x->blocksize = (int)sp[0]->s_n; x->sp = sp; // prepare for Lua signal_setmultiout PDLUA_DEBUG("pdlua_dsp: stack top %d", lua_gettop(__L())); @@ -1182,25 +1180,33 @@ static void pdlua_dsp(t_pdlua *x, t_signal **sp){ } if (lua_pcall(__L(), 4, 0, 0)) - { mylua_error(__L(), x, "dsp"); - } + lua_pop(__L(), 1); /* pop the global "pd" */ PDLUA_DEBUG("pdlua_dsp: end. stack top %d", lua_gettop(__L())); - int sigvecsize = sum + 1; - t_int* sigvec = getbytes(sigvecsize * sizeof(t_int)); + // Free existing sig_info if it exists + if (x->sig_info) { + freebytes(x->sig_info, sum * sizeof(t_pdlua_siginfo)); + x->sig_info = NULL; + } - sigvec[0] = (t_int)x; - - for (int i = 0; i < sum; i++) - sigvec[i + 1] = (t_int)sp[i]; + x->sig_info = (t_pdlua_siginfo *)getbytes(sum * sizeof(t_pdlua_siginfo)); - dsp_addv(pdlua_perform, sigvecsize, sigvec); - freebytes(sigvec, sigvecsize * sizeof(t_int)); + for (int i = 0; i < sum; i++) { + x->sig_info[i].vec = sp[i]->s_vec; +#if PD_MULTICHANNEL + x->sig_info[i].nchans = sp[i]->s_nchans ? sp[i]->s_nchans : 1; +#else + x->sig_info[i].nchans = 1; +#endif + } + + dsp_add(pdlua_perform, 1, x); } + static int pdlua_get_arguments(lua_State *L) { // Check if the first argument is a valid user data pointer @@ -1444,6 +1450,7 @@ static int pdlua_object_new(lua_State *L) o->pdlua_class = c; o->pdlua_class_gfx = c_gfx; o->sp = NULL; + o->sig_info = NULL; o->gfx.width = 80; o->gfx.height = 80; diff --git a/pdlua.h b/pdlua.h index 869ad89..55928bc 100644 --- a/pdlua.h +++ b/pdlua.h @@ -52,6 +52,14 @@ typedef struct _pdlua_gfx #endif } t_pdlua_gfx; +/** Structure to hold signal information. */ +typedef struct pdlua_siginfo +{ + t_float *vec; // Signal vector + int nchans; // Number of channels +} t_pdlua_siginfo; + + /** Pd object data. */ typedef struct pdlua { @@ -70,6 +78,7 @@ typedef struct pdlua t_pdlua_gfx gfx; // Holds state for graphics. t_class *pdlua_class; // Holds our class pointer. t_class *pdlua_class_gfx; // Holds our gfx class pointer. + t_pdlua_siginfo *sig_info; // Array of signal info structures t_signal **sp; // Array of signal pointers for multichannel audio. } t_pdlua; From e691179dbc107fa226a3807e9c0e91587cdcc8b3 Mon Sep 17 00:00:00 2001 From: Ben Wesch Date: Fri, 18 Oct 2024 08:31:33 +0200 Subject: [PATCH 2/3] properly free sig_info based on previous signal count --- pdlua.c | 9 +++++---- pdlua.h | 7 ++++--- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/pdlua.c b/pdlua.c index e14edba..565f134 100644 --- a/pdlua.c +++ b/pdlua.c @@ -742,9 +742,8 @@ static void pdlua_free( t_pdlua *o /**< The object to destruct. */) PDLUA_DEBUG("pdlua_free: end. stack top %d", lua_gettop(__L())); // Free sig_info if it exists - // FIXME: necessary? if (o->sig_info) { - freebytes(o->sig_info, (o->siginlets + o->sigoutlets) * sizeof(t_pdlua_siginfo)); + freebytes(o->sig_info, o->sig_count * sizeof(t_pdlua_siginfo)); o->sig_info = NULL; } @@ -1186,13 +1185,14 @@ static void pdlua_dsp(t_pdlua *x, t_signal **sp){ PDLUA_DEBUG("pdlua_dsp: end. stack top %d", lua_gettop(__L())); - // Free existing sig_info if it exists + // Free existing sig_info if it exists, using the old sig_count if (x->sig_info) { - freebytes(x->sig_info, sum * sizeof(t_pdlua_siginfo)); + freebytes(x->sig_info, x->sig_count * sizeof(t_pdlua_siginfo)); x->sig_info = NULL; } x->sig_info = (t_pdlua_siginfo *)getbytes(sum * sizeof(t_pdlua_siginfo)); + x->sig_count = sum; for (int i = 0; i < sum; i++) { x->sig_info[i].vec = sp[i]->s_vec; @@ -1451,6 +1451,7 @@ static int pdlua_object_new(lua_State *L) o->pdlua_class_gfx = c_gfx; o->sp = NULL; o->sig_info = NULL; + o->sig_count = 0; o->gfx.width = 80; o->gfx.height = 80; diff --git a/pdlua.h b/pdlua.h index 55928bc..9440b70 100644 --- a/pdlua.h +++ b/pdlua.h @@ -52,14 +52,14 @@ typedef struct _pdlua_gfx #endif } t_pdlua_gfx; + /** Structure to hold signal information. */ -typedef struct pdlua_siginfo +typedef struct { t_float *vec; // Signal vector int nchans; // Number of channels } t_pdlua_siginfo; - /** Pd object data. */ typedef struct pdlua { @@ -69,6 +69,8 @@ typedef struct pdlua t_inlet **in; int outlets; // Number of outlets. t_outlet **out; // The outlets themselves. + t_pdlua_siginfo *sig_info; // Array of signal info structures for perform function. + int sig_count; // Total number of signal iolets for sig_info memory management. int siginlets; // Number of signal inlets. int sigoutlets; // Number of signal outlets. int sig_warned; // Flag for perform signal errors. @@ -78,7 +80,6 @@ typedef struct pdlua t_pdlua_gfx gfx; // Holds state for graphics. t_class *pdlua_class; // Holds our class pointer. t_class *pdlua_class_gfx; // Holds our gfx class pointer. - t_pdlua_siginfo *sig_info; // Array of signal info structures t_signal **sp; // Array of signal pointers for multichannel audio. } t_pdlua; From 5027f71a69b7b73f6d40785e83b0ae9ade03768b Mon Sep 17 00:00:00 2001 From: Ben Wesch Date: Fri, 18 Oct 2024 11:52:36 +0200 Subject: [PATCH 3/3] free sig_info in pdlua_object_free --- pdlua.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/pdlua.c b/pdlua.c index 565f134..9ab1e55 100644 --- a/pdlua.c +++ b/pdlua.c @@ -741,12 +741,6 @@ static void pdlua_free( t_pdlua *o /**< The object to destruct. */) lua_pop(__L(), 1); /* pop the global "pd" */ PDLUA_DEBUG("pdlua_free: end. stack top %d", lua_gettop(__L())); - // Free sig_info if it exists - if (o->sig_info) { - freebytes(o->sig_info, o->sig_count * sizeof(t_pdlua_siginfo)); - o->sig_info = NULL; - } - // Collect garbage // If we don't do this here, it could potentially leak if no other pdlua objects are used afterwards lua_gc(__L(), LUA_GCCOLLECT); @@ -1190,10 +1184,10 @@ static void pdlua_dsp(t_pdlua *x, t_signal **sp){ freebytes(x->sig_info, x->sig_count * sizeof(t_pdlua_siginfo)); x->sig_info = NULL; } - + x->sig_info = (t_pdlua_siginfo *)getbytes(sum * sizeof(t_pdlua_siginfo)); x->sig_count = sum; - + for (int i = 0; i < sum; i++) { x->sig_info[i].vec = sp[i]->s_vec; #if PD_MULTICHANNEL @@ -1937,6 +1931,12 @@ static int pdlua_object_free(lua_State *L) free(o->out); o->out = NULL; } + + if (o->sig_info) + { + freebytes(o->sig_info, o->sig_count * sizeof(t_pdlua_siginfo)); + o->sig_info = NULL; + } } } PDLUA_DEBUG("pdlua_object_free: end. stack top is %d", lua_gettop(L));