/* * permut.c - applies a (random) permutation on a signal block * intended for spectral processing, dynwav * * Copyright (c) 2000-2003 by Tom Schouten * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <math.h> #include <stdlib.h> //#include "m_pd.h" #include "extlib_util.h" typedef union { float f; unsigned int i; }t_permutflint; typedef struct permutctl { char c_type; t_int *c_permutationtable; int c_blocksize; } t_permutctl; typedef struct permut { t_object x_obj; t_float x_f; t_permutctl x_ctl; } t_permut; static inline void permut_perform_permutation(t_float *S, int n, t_int *f) { t_int k,l; t_float swap; for(k=0; k<n; k++) { l = f[k]; while (l<k) l = f[l]; swap = S[k]; S[k] = S[l]; S[l] = swap; } } static void permut_random(t_permut *x, t_floatarg seed) { int i,j; int N = x->x_ctl.c_blocksize; int mask = N-1; t_int *p = x->x_ctl.c_permutationtable; int r, last = 0; t_permutflint flintseed; flintseed.f = (float)seed; srand(flintseed.i); if(p) { p[0] = rand() & mask; for (i=1;i<N;i++) { r = rand() & mask; j = 0; while(j<i) { if (p[j] == r) { r = (r + 1) & mask; j = 0; } else j++; } p[i] = r; } } } static void permut_bang(t_permut *x) { t_permutflint seed; seed.i = rand(); t_float floatseed = (t_float)seed.f; permut_random(x, floatseed); } static void permut_resize_table(t_permut *x, int size) { if (x->x_ctl.c_blocksize != size) { if (x->x_ctl.c_permutationtable) free(x->x_ctl.c_permutationtable); x->x_ctl.c_permutationtable = (t_int *)malloc(sizeof(t_int)*size); x->x_ctl.c_blocksize = size; /* make sure it's initialized */ permut_bang(x); } } static t_int *permut_perform(t_int *w) { t_float *in = (t_float *)(w[3]); t_float *out = (t_float *)(w[4]); t_permutctl *ctl = (t_permutctl *)(w[1]); t_int i; t_int n = (t_int)(w[2]); t_float x,y; t_int *p = ctl->c_permutationtable; if (in != out) for (i=0; i<n; i++) out[i] = in[i]; permut_perform_permutation(out, n, p); return (w+5); } static void permut_dsp(t_permut *x, t_signal **sp) { permut_resize_table(x, sp[0]->s_n); dsp_add(permut_perform, 4, &x->x_ctl, (t_int)sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec); } static void permut_free(t_permut *x) { if (x->x_ctl.c_permutationtable) free(x->x_ctl.c_permutationtable); } t_class *permut_class; static void *permut_new(void) { t_permut *x = (t_permut *)pd_new(permut_class); outlet_new(&x->x_obj, gensym("signal")); x->x_ctl.c_permutationtable = 0; x->x_ctl.c_blocksize = 0; permut_resize_table(x, 64); permut_random(x, 0); return (void *)x; } void permut_tilde_setup(void) { //post("permut~ v0.1"); permut_class = class_new(gensym("permut~"), (t_newmethod)permut_new, (t_method)permut_free, sizeof(t_permut), 0, A_DEFFLOAT, 0); CLASS_MAINSIGNALIN(permut_class, t_permut, x_f); class_addmethod(permut_class, (t_method)permut_random, gensym("random"), A_FLOAT, 0); class_addmethod(permut_class, (t_method)permut_bang, gensym("bang"), 0); class_addmethod(permut_class, (t_method)permut_dsp, gensym("dsp"), A_CANT, 0); }