Hello again,
Another probable noob style question... I have built a relatively simple external to generate low-passed random numbers (ie - skewed to the low end of a range). Nothing complicated, it takes two arguments - the range and a 'Q' value and when it receives a bang it spits out a random integer much like the native random object does. The external is working properly as far as I can tell, but it seems to be causing some amount of crashes. I had some difficulty getting it to work in the first place which was down to memory allocation issues and I suspect that may still be the problem now, but I have no idea why. the full code is as follows:
#ifdef WIN_VERSION
#define _CRT_RAND_S
#endif
// ---------- include
#include "ext.h"
#include "ext_obex.h"
// ---------- object
typedef struct _lprand
{
t_object obj;
long *rndarray;
long range;
long q;
void *out;
} t_lprand;
// ---------- function prototypes
// standard set
void *lprand_new(t_symbol *s, long argc, t_atom *argv);
void lprand_free(t_lprand *x);
void lprand_assist(t_lprand *x, void *b, long m, long a, char *s);
// additional
void lprand_bang(t_lprand *x);
long rnum(long range);
long lopass(t_lprand *x, long range, long q);
// ---------- global class pointer
void *lprand_class;
// ---------- main
void ext_main(void *r)
{
t_class *c;
c = class_new("lprand", (method)lprand_new, (method)lprand_free, (long)sizeof(t_lprand), 0L, A_GIMME, 0);
class_addmethod(c, (method)lprand_bang, "bang", 0);
class_register(CLASS_BOX, c);
lprand_class = c;
post("lprand object instantiated.");
}
// ---------- assist
void lprand_assist(t_lprand *x, void *b, long m, long a, char *s)
{
if (m == ASSIST_INLET) {
sprintf(s, "Inlet %ld accepts a bang", a);
}
else {
sprintf(s, "Outlet %ld delivers a low-passed random number.", a);
}
}
// ---------- rnum (random number)
long rnum(long range)
{
long rand;
#ifdef WIN_VERSION
rand_s(&rand);
#else
rand = random();
#endif
rand = rand % range;
return rand;
}
// ---------- lopass (low passed random number)
long lopass(t_lprand *x, long range, long q)
{
long counter;
long minimum;
for (counter = 0; counter < q; counter++) {
x->rndarray[counter] = rnum(range);
}
minimum = x->rndarray[0];
for (counter = 0; counter < q; counter++) {
if (x->rndarray[counter] < minimum) {
minimum = x->rndarray[counter];
}
}
return minimum;
}
// ---------- bang
void lprand_bang(t_lprand *x)
{
long rand = lopass(x, x->range, x->q);
outlet_int(x->out, rand);
}
// ---------- free
void lprand_free(t_lprand *x)
{
sysmem_freeptr(x->rndarray);
}
// ---------- new
void *lprand_new(t_symbol *s, long argc, t_atom *argv)
{
t_lprand *x = NULL;
long range, q;
if (argc != 2) {
post("Incorrect number of arguments for the lprand object.");
return NULL;
}
range = atom_getlong(argv);
if (range < 1) {
post("Range argument must be greater than 1.");
return NULL;}
q = atom_getlong(argv+1);
if (q < 1 || q > 10) {
post("Q argument out of bounds. It must be between 1 and 10 (inclusive).");
return NULL;
}
if ((x = (t_lprand *)object_alloc(lprand_class))) {
x->rndarray = (long *)sysmem_newptrclear(q);
x->range = range;
x->q = q;
x->out = intout((t_lprand *)x);
}
return x;
}
Can anyone see what might be causing this? I'm still (slowly) learning my way around the API. Originally I was attempting to just create the rndarray with malloc in the lopass function but after looking through the documentation and examples thought the sysmem_xxx stuff was a better way to ensure compatibility. Perhaps I have implemented it incorrectly?
Thanks for any thoughts.