EDIT:
The original thread title was: Interrupt/disable perform method while reallocating memory
I changed it, as it was based on searching for a solution caused by faulty code.
After discarding my code the topic of the thread got a new direction.
Hi,
I try to write an external, which calculates the averages of samples at their positions over time.
For example:
With average time = 3:
3 signals given over 3 blocks: [1, 3, 5 ...], [2, 4, 6...],[1, 3, 5...] should result in [1.33, 3,33, 5,33, ...]
The example code below works, as long as I don't try to resize the average time to a lower value while dsp is running.
On changing the average time while dsp is on, my code reallocates memory for the average vector. The result is an exception in the perform method in line 53 x->avg[n] -= x->sampel_arr[x->pos][n];
The commented lines using x->busy were an attempt to use a switch. But the code of the switch is never used, so it doesn't work.
Does anybody have an idea how to bypass the perform method while memory is reallocated?
#include "m_pd.h"
#include <string.h>
#include <stdlib.h>
static t_class *average_tilde_class;
typedef struct _average_tilde {
t_object x_obj;
t_int len_delay;
t_int block_size;
t_int pos;
t_sample **sampel_arr;
t_float *avg;
t_int busy;
t_inlet* x_in;
t_outlet* x_out;
} t_average_tilde;
void average_tilde_free(t_average_tilde *x)
{
// Deallocate rows
for (int i = 0; i < x->len_delay; ++i)
free(x->sampel_arr[i]);
// Deallocate columns
free(x->sampel_arr);
// Deallocate avg
free(x->avg);
}
t_int *average_tilde_perform(t_int *w)
{
t_average_tilde *x = (t_average_tilde *)(w[1]);
t_sample *in = (t_sample *)(w[2]);
t_sample *out = (t_sample *)(w[3]);
int block = (int)(w[4]);
/*if (x->busy == 1) {
while (block--) {
*out++ = *in++;
}
return (w + 5);
};*/
float val;
for (int n = 0; n < x->block_size; n++) {
x->avg[n] -= x->sampel_arr[x->pos][n];
val = in[n] / x->block_size;
x->avg[n] += val;
x->sampel_arr[x->pos][n] = val;
*out++ = x->avg[n];
}
x->pos++;
if (x->pos == x->len_delay) x->pos = 0;
return (w + 5);
}
void resize_avg_array(t_average_tilde *x)
{
int i,j;
/*post("resize");
x->busy = 1;*/
// Allocate the columns
x->sampel_arr = (int**)realloc(x->sampel_arr, x->len_delay * sizeof(int*));
/*if (x->sampel_arr == NULL)
post("error");*/
// The new column's pointer must be initialised to NULL
for (i = 0; i < x->len_delay; i++)
x->sampel_arr[i] = NULL;
// Allocate the rows
for (i = 0; i < x->len_delay; i++) {
x->sampel_arr[i] = (float*)realloc(x->sampel_arr[i], x->block_size * sizeof(float));
/*if (x->sampel_arr == NULL)
post("error");*/
}
// Initialize the element(s)
for (i = 0; i < x->len_delay; i++)
for (j = 0; j < x->block_size; j++)
x->sampel_arr[i][j] = 0.0;
// Allocate avg-array
x->avg = realloc(x->avg, x->block_size * sizeof(float));
/*if (x->avg == NULL)
post("error");*/
// Initialize avg-array
for (i = 0; i < x->block_size; i++)
x->avg[i] = 0.0;
/*x->busy = 0;
post("resize2");
post(" ");*/
}
void average_tilde_dsp(t_average_tilde *x, t_signal **sp)
{
x->block_size = sp[0]->s_n;
float arr_size = sizeof(x->sampel_arr) / sizeof(x->sampel_arr[0][0]);
if (x->block_size * x->len_delay != arr_size)
resize_avg_array(x);
dsp_add(average_tilde_perform, 4,
x,
sp[0]->s_vec,
sp[1]->s_vec,
sp[0]->s_n);
}
void set_len_delay(t_average_tilde *x, t_floatarg f)
{
if ((int)f > 0) x->len_delay = (int)f;
resize_avg_array(x);
}
void init_array(t_average_tilde *x)
{
int i = 0, j = 0;
// Allocate the columns
x->sampel_arr = (int**)calloc(x->len_delay, sizeof(int*));
// Allocate the rows
for (i = 0; i < x->len_delay; i++)
x->sampel_arr[i] = (float*)calloc(x->block_size, sizeof(float));
// Initialize the element(s)
for (i = 0; i < x->len_delay; i++)
for (j = 0; j < x->block_size; j++)
x->sampel_arr[i][j] = 0.0;
// Initialize avg-array
x->avg = realloc(x->avg, x->block_size * sizeof(float));
for (j = 0; j < x->block_size; j++)
x->avg[j] = 0.0;
}
void *average_tilde_new(t_floatarg f)
{
t_average_tilde *x = (t_average_tilde *)pd_new(average_tilde_class);
// initialize values with defaults
x->len_delay = ((int)f > 0) ? (int)f : 10;
x->block_size = 64;
x->pos = 0;
init_array(x);
x->busy = 0;
x->x_out = outlet_new(&x->x_obj, &s_signal);
return (void *)x;
}
void init_average(void) {
average_tilde_class = class_new(gensym("r_avg~"),
(t_newmethod)average_tilde_new,
(t_method)average_tilde_free,
sizeof(t_average_tilde),
CLASS_DEFAULT,
A_DEFFLOAT, 0);
class_addmethod(average_tilde_class,
(t_method)average_tilde_dsp, gensym("dsp"), 0);
CLASS_MAINSIGNALIN(average_tilde_class, t_average_tilde, len_delay);
class_addfloat(average_tilde_class, set_len_delay);
}
void helloworld_setup(void) {
init_average();
}```
// The code for reallocation is taken from here:
// http://hesham-rafi.blogspot.de/2009/02/resize-2d-matrix-using-realloc.html