On Wed, Aug 20, 2014 at 10:30 AM, IOhannes m zmoelnig <[email protected]>
wrote:

> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA256
>
> On 2014-08-19 22:09, Alexandros Drymonitis wrote:
> >
> > Here's my perform routine: t_int *vanDerPol_perform(t_int *w) { //
> > Copy the object pointer t_vanDerPol *x = (t_vanDerPol *) (w[1]);
> >
> > // Copy signal vector pointers t_float *frequency = (t_float *)
> > (w[2]); t_float *factor = (t_float*) (w[3]); t_float *excitor_freq
> > = (t_float*) (w[4]); t_float *excitor_amp = (t_float*) (w[5]);
> > t_float *output = (t_float *) (w[6]);
>
> the scalar type for signals is really *t_sample*.
> you should NOT use *t_float* for these kind of things (though in
> practice they two might always be the same).
> if you are following a tutorial that suggests to use t_float, then
> report a bug to the author of the tutorial.
>
OK, changed it.

>
> >
> > // Copy the signal vector size t_int n = w[7];
> >
> > // Dereference components from the object structure float twopi =
> > x->x_twopi;
>
> now that looks very much like a constant, which you don't need to
> modify per-object...
>
I'm setting its value in the new instance routine by multiplying atan(1.0)
by 8, instead of writing it as a macro.

>
> > // excitor code si = *excitor_freq++ * si_factor; phase_local =
> > phase / step; drive_sine = cos(phase_local * twopi) *
> > *excitor_amp++;
>
> i guess you are copying the CSound code here.
> however,  i really think it would be much better to use an "external"
> excitor, that is: instead of having an input for the frequency and
> another input for the amplitude of the internal sine oscillator, you
> might want to have a single input for an in-patch sine-oscillator.
>
> so your patch would look like:
> |
> [osc~ 666]
> |
> [*~ 0.42]
> |
> [vanderpol~]
> |
>
> (it might make sense to make the excitor input the first one, so you
> can use it
>
> this has two huge advantages:
> #1 Pd's oscillator is known to work; if it ever breaks, it will be
> fixed immediately.
> thus you don't need to re-code existing functionality, possibly
> introducing bugs.
>
> #2 you might want to use another exciter waveform, and get results
> unheard of.
> without any additional coding effort! for free!!
>
Did that as well.

>
> >
> > // van der Pol code c = 2 - 2 * cos(*frequency++ * twopi / sr);
>
> again, it might be better to use an external signal to drive this
> oscillator.
>
How? Can you provide a patch example? Or should I just translate this in an
abstraction?

>
>
> > aa = (-c) * ax + *factor++ * (1 - ax * ax) * av; av += aa; ax = ax
> > + av + drive_sine; *output++ = av;
>
> hmm.
> you are resetting "av" and "ax" to 0 for each DSP-block.
> most likely this is not what you want, as the srtucture looks like a
> feedback filter (IIR), so you need to store ax&av between DSP-blocks.
>
Fixed that too and the result is indeed much better. I don't think though
that this implementation is good. The output doesn't really look like the
example one finds online.
I've attached the .c file if anyone wants to take a look.

>
>
> fgmsdar
> IOhannes
>
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v1
>
> iQIbBAEBCAAGBQJT9E58AAoJELZQGcR/ejb4BOIP+PL3nuKFhAMbv3uJDOn6QElf
> ykV7IpVJ9eWfO8dYUguT/afrUjKbEytWoq0rgC5mKPvKXvWK3OZaIxgQh6D2uqEr
> /ar1DyCu0daZh8V5ic2PC3QMdF/3eumRyLKyZJ4iWURhSsIrnamwVNONSc00wKPa
> ck3jQx05Z7v9vgCBFiXpgj1SuyihJSpgCPNU5DYpRmwmvGNt3BgyJv9xKjQFhLvO
> un3bSjeStijmRftz9g2SwoXQkLrHU2ieHvqBlE4iSj+V9dalxx4SIvH5Bzn74u+X
> MQMS/ndF8YIvlmnP91F0GXKuVNS8YqbgJsNY+69JEbgLvcZzsCTUUv1MDKyxQrMy
> 7jr/JGslJcj/DlG9P2xWJ2OeuT7uCv6uhYgGTW2VXYC266hmBQ8BVezl9BmW9PFU
> yD9UeBie94sNV7R38G48FVdb9hztFVel58hJG3jJjDpVir5zRYITfcv2DMf1xbNb
> rsrwbkNxxeCY8euhZiaTe03qgOkTYXigwJgfl3D7gY3fPGRd/NFw45sKk7VmmTd1
> LLn8DEDOCAUMGG+Nbl/sACy+iJSEy/MmsaNVe0t58W6sYYSmRm37xYm4MtIdwGRP
> N+PdS3gpUwFPKgzQA+1FMdByh78M9KZu9eqIUoCKxvrU43QFmqT4+wehZx2yNF3/
> NhVFjIZx8D6+719+VKA=
> =mfTs
> -----END PGP SIGNATURE-----
>
> _______________________________________________
> Pd-dev mailing list
> [email protected]
> http://lists.puredata.info/listinfo/pd-dev
>
/******************************************
 * van der Pol oscillator                 *
 * translated from CSound's FLOSS manuals *
 * written by Alexandros Drymonitis       *
 ******************************************/

// Header files required by Pure Data
#include "m_pd.h"
#include "math.h"

// The class pointer
static t_class *van_der_Pol_class;

// The object structure
typedef struct _van_der_Pol {
	// The Pd object
	t_object obj;
	// Convert floats to signals
	t_float x_f;
	// Other variables
	t_float x_twopi;
	t_float x_sr;
	t_float x_av;
	t_float x_ax;
} t_van_der_Pol;

// Function prototypes
void *van_der_Pol_new(void);
void van_der_Pol_dsp(t_van_der_Pol *x, t_signal **sp);
t_int *van_der_Pol_perform(t_int *w);

// The Pd class definition function
void van_der_Pol_tilde_setup(void)
{
	// Initialize the class
	van_der_Pol_class = class_new(gensym("van_der_Pol~"), (t_newmethod)van_der_Pol_new, 0, sizeof(t_van_der_Pol), 0, 0);

	// Specify signal input, with automatic float to signal conversion
	CLASS_MAINSIGNALIN(van_der_Pol_class, t_van_der_Pol, x_f);

	// Bind the DSP method, which is called when the DACs are turned on
	class_addmethod(van_der_Pol_class, (t_method)van_der_Pol_dsp, gensym("dsp"), A_CANT, 0);

	// Print authorship to Pd window
	post("van_der_Pol~: van der Pol oscillator, translated from CSound's FLOSS manuals\n written by Alexandros Drymonitis");
}

// The new instance routine
void *van_der_Pol_new(void)
{
	// Basic object setup

	// Instantiate a new vanDerPol~ object
	t_van_der_Pol *x = (t_van_der_Pol *) pd_new(van_der_Pol_class);

	// Create two addition signal inlets
	inlet_new(&x->obj, &x->obj.ob_pd, gensym("signal"), gensym("signal"));
	inlet_new(&x->obj, &x->obj.ob_pd, gensym("signal"), gensym("signal"));

	// Create one signal outlet
	outlet_new(&x->obj, gensym("signal"));

	// Initialize 2pi and the oscillator's samples
	x->x_twopi = 8 * atan(1.0);
	x->x_av = 0;
	x->x_ax = 0;

	// get system's sampling rate and set sampling interval and factor
  x->x_sr = sys_getsr();

	// Return a pointer to the new object
	return x;
}

// The perform routine
t_int *van_der_Pol_perform(t_int *w)
{
	// Copy the object pointer
	t_van_der_Pol *x = (t_van_der_Pol *) (w[1]);

	// Copy signal vector pointers
	t_sample *excitor = (t_sample*) (w[2]);
	t_sample *frequency = (t_sample *) (w[3]);
	t_sample *factor = (t_sample*) (w[4]);
	t_sample *output = (t_sample *) (w[5]);

	// Copy the signal vector size
	t_int n = w[6];

	// Dereference components from the object structure
	float twopi = x->x_twopi;
	float sr = x->x_sr;
	float av = x->x_av;
	float ax = x->x_ax;
	// Local variables
	float aa;
	// damping factor
	float c;

	// Perform the DSP loop
	while(n--){
		c = 2 - 2 * cos(*frequency++ * twopi / sr);
		aa = (-c) * ax + *factor++ * (1 - ax * ax) * av;
		av += aa;
		ax = ax + av + *excitor++;
		*output++ = av;
		}

		// Reset object's variables
		x->x_av = av;
		x->x_ax = ax;

	// Return the next address in the DSP chain
	return w + 7;
}

// The DSP method
void van_der_Pol_dsp(t_van_der_Pol *x, t_signal **sp)
{
  // Check if samplerate has changed
  if(x->x_sr != sp[0]->s_sr){
		if(! sp[0]->s_sr){
    error("zero sampling rate!");
    return;
	}
  x->x_sr = sp[0]->s_sr;
  }

	/* Attach the object to the DSP chain, passing the DSP routine vanDerPol_perform(),
	inlet and outlet pointers, and the signal vector size */
	dsp_add(van_der_Pol_perform, 6, x, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, sp[0]->s_n);
}
_______________________________________________
Pd-dev mailing list
[email protected]
http://lists.puredata.info/listinfo/pd-dev

Reply via email to