diff --git a/simplex~-help.pd b/simplex~-help.pd index 2441775..15e2ea9 100644 --- a/simplex~-help.pd +++ b/simplex~-help.pd @@ -1,13 +1,13 @@ -#N struct 1082-path-template float x float y array 1082-data 1082-data-template; -#N struct 1082-data-template float x float y; -#N struct 1085-path-template float x float y array 1085-data 1085-data-template; -#N struct 1085-data-template float x float y; -#N struct 1086-path-template float x float y array 1086-data 1086-data-template; -#N struct 1086-data-template float x float y; -#N struct 1087-path-template float x float y array 1087-data 1087-data-template; -#N struct 1087-data-template float x float y; -#N struct 1091-path-template float x float y array 1091-data 1091-data-template; -#N struct 1091-data-template float x float y; +#N struct 1005-path-template float x float y array 1005-data 1005-data-template; +#N struct 1005-data-template float x float y; +#N struct 1008-path-template float x float y array 1008-data 1008-data-template; +#N struct 1008-data-template float x float y; +#N struct 1009-path-template float x float y array 1009-data 1009-data-template; +#N struct 1009-data-template float x float y; +#N struct 1010-path-template float x float y array 1010-data 1010-data-template; +#N struct 1010-data-template float x float y; +#N struct 1014-path-template float x float y array 1014-data 1014-data-template; +#N struct 1014-data-template float x float y; #N canvas 366 153 1104 831 10; #N canvas 200 100 298 221 (subpatch) 0; #X obj 50 70 inlet~; @@ -133,7 +133,6 @@ #X text 834 237 <-- activate to see visualizations below; #X obj 599 738 output~; #X msg 890 146 seed; -#X text 379 83 single numerical argument sets octave count (default: 1); #X text 402 104 additional numerical argument sets persistence (default: 0.5), f 61; #X msg 890 125 normalize 0; #X text 967 125 on/off; @@ -204,6 +203,9 @@ #X text 449 695 circular scan \, slowly moving upwards (i.e. spiral movement) \, resulting in a periodic waveform. sampled values displace y-position., f 22; #X text 611 695 the periodic signal based on the spiral movement., f 23; #X text 806 695 scanning a spherical shape \, moving in 4th dimension (w-coord). sampled values displace radius., f 23; +#X text 890 167 <-- custom octave scale factors; +#X msg 809 167 coeffs 1 3 5; +#X text 379 83 single numerical argument sets octave count (default: 1 \, max: 24), f 65; #X connect 0 0 51 0; #X connect 0 1 16 0; #X connect 1 0 10 2; @@ -244,7 +246,7 @@ #X connect 32 0 30 2; #X connect 32 0 34 2; #X connect 33 0 29 0; -#X connect 34 0 67 0; +#X connect 34 0 66 0; #X connect 35 0 40 0; #X connect 36 0 17 0; #X connect 37 0 5 0; @@ -257,26 +259,26 @@ #X connect 40 0 34 1; #X connect 41 0 33 1; #X connect 44 0 47 0; -#X connect 57 0 11 0; -#X connect 57 0 1 0; -#X connect 67 0 41 0; -#X connect 71 0 34 3; -#X connect 71 0 10 1; -#X connect 71 0 6 1; -#X connect 71 0 4 1; -#X connect 73 0 85 0; -#X connect 74 0 75 0; -#X connect 75 0 82 0; -#X connect 76 0 82 0; -#X connect 77 0 78 0; -#X connect 78 0 83 0; -#X connect 79 0 76 0; -#X connect 80 0 67 0; -#X connect 80 0 14 0; -#X connect 80 0 26 0; -#X connect 80 0 8 0; -#X connect 81 0 67 1; -#X connect 81 0 26 1; -#X connect 81 0 14 1; -#X connect 81 0 8 1; -#X connect 85 0 72 0; +#X connect 56 0 11 0; +#X connect 56 0 1 0; +#X connect 66 0 41 0; +#X connect 70 0 34 3; +#X connect 70 0 10 1; +#X connect 70 0 6 1; +#X connect 70 0 4 1; +#X connect 72 0 84 0; +#X connect 73 0 74 0; +#X connect 74 0 81 0; +#X connect 75 0 81 0; +#X connect 76 0 77 0; +#X connect 77 0 82 0; +#X connect 78 0 75 0; +#X connect 79 0 66 0; +#X connect 79 0 14 0; +#X connect 79 0 26 0; +#X connect 79 0 8 0; +#X connect 80 0 66 1; +#X connect 80 0 26 1; +#X connect 80 0 14 1; +#X connect 80 0 8 1; +#X connect 84 0 71 0; diff --git a/simplex~-help.pd.png b/simplex~-help.pd.png index fc82662..b446487 100644 Binary files a/simplex~-help.pd.png and b/simplex~-help.pd.png differ diff --git a/simplex~.c b/simplex~.c index 8fa2060..5523b50 100644 --- a/simplex~.c +++ b/simplex~.c @@ -9,6 +9,7 @@ #define PERSISTENCE 0.5f #define MAX_DIMENSIONS 4 +#define MAX_OCTAVES 24 #define F2 0.36602540378f // 0.5*(sqrt(3.0)-1.0); @@ -33,6 +34,7 @@ typedef struct _simplex_tilde { t_inlet *inlet_persistence; int normalize; int octaves; + t_float octave_factors[MAX_OCTAVES]; int perm[512]; } t_simplex_tilde; @@ -388,19 +390,33 @@ static t_float snoise4(t_simplex_tilde *x, t_float x_in, t_float y_in, t_float z } static inline t_float generate_noise(t_simplex_tilde *x, t_float *pos, t_float persistence, int channel_count) { - t_float result = 0.0, persistence_sum = 0.0, scale, coeff; + t_float result = 0.0f; + t_float coeff = 1.0f; + t_float normalize_factor = 1.0f; + t_float scale; + + // normalization according to inversed geometric series including a^0 based + // on given persistence: + // + // a - 1 + // s = ------- + // a^n - 1 + // + if (x->normalize) { + normalize_factor = persistence - 1.0f; + normalize_factor /= pow(persistence, x->octaves) - 1.0f; + } static t_float (*noise_func[])(t_simplex_tilde *, t_float, t_float, t_float, t_float) = { snoise1, snoise2, snoise3, snoise4 }; - for (int octave = 0; octave < x->octaves; octave++) { - scale = pow(2, octave); - coeff = pow(persistence, octave); - persistence_sum += fabs(coeff); + if (octave > 0) + coeff *= persistence; + scale = x->octave_factors[octave]; result += noise_func[channel_count-1](x, pos[0] * scale, pos[1] * scale, pos[2] * scale, pos[3] * scale) * coeff; } - return x->normalize ? result / persistence_sum : result; + return result * normalize_factor; } static t_int *simplex_tilde_perform(t_int *w) { @@ -426,8 +442,14 @@ void simplex_tilde_dsp(t_simplex_tilde *x, t_signal **sp) { dsp_add(simplex_tilde_perform, 6, x, (t_int)sp[0]->s_n, (t_int)sp[0]->s_nchans, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec); } +static inline void init_octave_factors(t_simplex_tilde *x){ + for (int octave = 0; octave < x->octaves; octave++) + x->octave_factors[octave] = (t_float)(1 << octave); +} + static void simplex_tilde_octaves(t_simplex_tilde *x, t_floatarg f){ - x->octaves = fastfloor(f); + x->octaves = fastfloor(min(MAX_OCTAVES, f)); + init_octave_factors(x); } static void simplex_tilde_normalize(t_simplex_tilde *x, t_floatarg f){ @@ -446,6 +468,16 @@ static void simplex_tilde_seed(t_simplex_tilde *x, t_symbol *s, int ac, t_atom * (void)s; } +static void simplex_tilde_coeffs(t_simplex_tilde *x, t_symbol *s, int ac, t_atom *av) { + int i; + x->octaves = min(MAX_OCTAVES, ac); + for (i = 0; i < x->octaves; i++){ + x->octave_factors[i] = atom_getfloat(av); + av++; + } + (void)s; +} + static void simplex_tilde_free(t_simplex_tilde *x){ inlet_free(x->inlet_persistence); } @@ -466,8 +498,10 @@ static void *simplex_tilde_new(t_symbol *s, int ac, t_atom *av) { pd_error(x, "[simplex~]: invalid argument"); ac--, av++; } - x->octaves = ac-- ? atom_getint(av++) : 1; + x->octaves = ac-- ? min(MAX_OCTAVES, atom_getint(av++)) : 1; persistence = ac>0 ? atom_getfloat(av) : PERSISTENCE; + init_octave_factors(x); + x->inlet_persistence = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); pd_float((t_pd *)x->inlet_persistence, persistence); outlet_new(&x->x_obj, &s_signal); @@ -484,6 +518,7 @@ void simplex_tilde_setup(void) { class_addmethod(simplex_tilde_class, nullfn, gensym("signal"), 0); class_addmethod(simplex_tilde_class, (t_method)simplex_tilde_dsp, gensym("dsp"), 0); class_addmethod(simplex_tilde_class, (t_method)simplex_tilde_seed, gensym("seed"), A_GIMME, 0); + class_addmethod(simplex_tilde_class, (t_method)simplex_tilde_coeffs, gensym("coeffs"), A_GIMME, 0); class_addmethod(simplex_tilde_class, (t_method)simplex_tilde_octaves, gensym("octaves"), A_FLOAT, 0); class_addmethod(simplex_tilde_class, (t_method)simplex_tilde_normalize, gensym("normalize"), A_FLOAT, 0); class_addmethod(simplex_tilde_class, (t_method)simplex_tilde_persistence, gensym("persistence"), A_FLOAT, 0);