[PD-cvs] pd/src d_fft.c,1.2,1.2.4.1 d_global.c,1.2,1.2.4.1 d_math.c,1.2,1.2.4.1 d_osc.c,1.2,1.2.4.1 d_soundfile.c,1.4,1.4.4.1 d_ugen.c,1.3,1.3.4.1 g_array.c,1.3,1.3.4.1

Tim Blechmann timblech at users.sourceforge.net
Fri Nov 5 14:56:01 CET 2004


Update of /cvsroot/pure-data/pd/src
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv25059

Modified Files:
      Tag: devel_0_38
	d_fft.c d_global.c d_math.c d_osc.c d_soundfile.c d_ugen.c 
	g_array.c 
Log Message:
devel_0_38

Index: g_array.c
===================================================================
RCS file: /cvsroot/pure-data/pd/src/g_array.c,v
retrieving revision 1.3
retrieving revision 1.3.4.1
diff -C2 -d -r1.3 -r1.3.4.1
*** g_array.c	6 Sep 2004 20:20:33 -0000	1.3
--- g_array.c	5 Nov 2004 13:55:58 -0000	1.3.4.1
***************
*** 10,13 ****
--- 10,19 ----
  #include <math.h>
  
+ 
+ /* Tim Blechmann: garray thread locks: */
+ #ifdef GARRAY_THREAD_LOCK
+ #include <pthread.h>
+ #endif /* GARRAY_THREAD_LOCK */
+ 
  /* see also the "plot" object in g_scalar.c which deals with graphing
[...1189 lines suppressed...]
--- 1722,1740 ----
      else garray_redraw(x);
      if (x->x_usedindsp) canvas_update_dsp();
+ #ifdef GARRAY_THREAD_LOCK /* TB: array lock */
+     garray_unlock(x); 
+ #endif
  }
  
  static void garray_print(t_garray *x)
  {  
+ #ifdef GARRAY_THREAD_LOCK /* TB: array lock */
+     garray_lock(x); 
+ #endif
      post("garray %s: template %s, length %d",
          x->x_name->s_name, x->x_templatesym->s_name, x->x_n);
+ #ifdef GARRAY_THREAD_LOCK /* TB: array lock */
+     garray_unlock(x); 
+ #endif
  }
  

Index: d_soundfile.c
===================================================================
RCS file: /cvsroot/pure-data/pd/src/d_soundfile.c,v
retrieving revision 1.4
retrieving revision 1.4.4.1
diff -C2 -d -r1.4 -r1.4.4.1
*** d_soundfile.c	6 Sep 2004 20:20:33 -0000	1.4
--- d_soundfile.c	5 Nov 2004 13:55:58 -0000	1.4.4.1
***************
*** 12,15 ****
--- 12,17 ----
  objects use Posix-like threads.  */
  
+ /* threaded soundfiler by Tim Blechmann */
+ 
  #ifndef MSW
  #include <unistd.h>
***************
*** 25,28 ****
--- 27,31 ----
  
  #include "m_pd.h"
+ #include "g_canvas.h"
  
  #define MAXSFCHANS 64
***************
*** 886,890 ****
  
  /* ------- soundfiler - reads and writes soundfiles to/from "garrays" ---- */
! #define DEFMAXSIZE 4000000      /* default maximum 16 MB per channel */
  #define SAMPBUFSIZE 1024
  
--- 889,898 ----
  
  /* ------- soundfiler - reads and writes soundfiles to/from "garrays" ---- */
! 
! #ifndef THREADED_SF
! #define DEFMAXSIZE 4000000 	/* default maximum 16 MB per channel */
! #else
! #define DEFMAXSIZE 40000000 /* threaded we should be able to hande a bit more */
! #endif
  #define SAMPBUFSIZE 1024
  
***************
*** 898,901 ****
--- 906,1766 ----
  } t_soundfiler;
  
+ #ifdef THREADED_SF
+ #include <sched.h>
+ #ifdef _POSIX_MEMLOCK
+ #include <sys/mman.h>
+ #endif /* _POSIX_MEMLOCK */
+ 
+ static pthread_t sf_thread_id; /* id of soundfiler thread */
+ static pthread_attr_t sf_attr;
+ 
+ typedef struct _sfprocess
+ {
+ 	void (* process) (t_soundfiler *,t_symbol *, 
+ 		      int, t_atom *); /* function to call */
+     t_soundfiler * x;        /* soundfiler */
+     int argc;  
+     t_atom * argv;
+     struct _sfprocess * next;  /* next object in queue */
+     pthread_mutex_t mutex;
+ } t_sfprocess;
+ 
+ /* this is the queue for all soundfiler objects */
+ typedef struct _sfqueue
+ {
+     t_sfprocess * begin;
+     t_sfprocess * end;
+     pthread_mutex_t mutex;
+     pthread_cond_t cond;
+ } t_sfqueue;
+ 
+ static t_sfqueue * soundfiler_queue; 
+ 
+ #ifdef DEBUG 
+ #define SFDEBUG
+ #endif
+ 
+ #define SFDEBUG
+ 
+ /* we fill the queue */
+ void soundfiler_queue_add(void (* process) (t_soundfiler *,t_symbol *,
+ 											int,t_atom *), void * x, 
+ 						  int argc, t_atom * argv)
+ {
+     /* preparing entry */
+     t_sfprocess * last_entry = (t_sfprocess*)getbytes(sizeof(t_sfprocess));
+ 
+ #ifdef SFDEBUG
+     post("adding process to queue");
+ #endif
+ 
+ 	pthread_mutex_init(&(last_entry->mutex), NULL);
+     pthread_mutex_lock(&(last_entry->mutex));
+     last_entry->process = process;
+     last_entry->x = x;
+     last_entry->argc = argc;
+     last_entry->argv = copybytes (argv, argc * sizeof(t_atom));
+     last_entry->next = NULL; 
+     pthread_mutex_unlock(&(last_entry->mutex));
+ 
+     /* add new entry to queue */ 
+     pthread_mutex_lock(&(soundfiler_queue->mutex));
+ 
+     if (soundfiler_queue->begin==NULL)
+     {
+ 		soundfiler_queue->begin=last_entry;
+ 		soundfiler_queue->end=last_entry;
+     }
+     else 
+     {
+ 		pthread_mutex_lock(&(soundfiler_queue->end->mutex));
+ 		soundfiler_queue->end->next=last_entry;
+ 		pthread_mutex_unlock(&(soundfiler_queue->end->mutex));
+ 		soundfiler_queue->end=last_entry;
+     }
+ 
+ 
+     if ( soundfiler_queue->begin == soundfiler_queue->end )
+     {
+ #ifdef DEBUG
+ 		post("signaling");
+ #endif
+ 		pthread_mutex_unlock(&(soundfiler_queue->mutex));
+ 
+ 		/* and signal the helper thread */
+ 		pthread_cond_signal(&(soundfiler_queue->cond));
+     }
+     else
+     {
+ #ifdef DEBUG
+ 		post("not signaling");
+ #endif
+ 		pthread_mutex_unlock(&(soundfiler_queue->mutex));
+     }
+     return;
+ }
+ 
+ /* global soundfiler thread ... sleeping until signaled */
+ void soundfiler_thread(void)
+ {    
+ 	t_sfprocess * me;
+     int i;
+ 	t_sfprocess * next;
+ 	while (1)
+     {
+ #ifdef DEBUG
+ 		post("Soundfiler sleeping");
+ #endif
+ 		pthread_cond_wait(&soundfiler_queue->cond, &soundfiler_queue->mutex);
+ #ifdef DEBUG
+ 		post("Soundfiler awake");
+ #endif
+ 
+ 		/* work on the queue */
+ 		while (soundfiler_queue->begin!=NULL)
+ 		{
+ 			post("soundfiler: locked queue");
+ 			/* locking process */
+ 			pthread_mutex_lock(&(soundfiler_queue->begin->mutex));
+ 	    
+ 			me = soundfiler_queue->begin;
+ 		
+ 			pthread_mutex_unlock(&(me->mutex));
+ 			pthread_mutex_unlock(&(soundfiler_queue->mutex)); 
+ #ifdef DEBUG
+ 			post("soundfiler: mutex unlocked, running process");
+ #endif
+ 
+ 			/* running the specific function */
+ 			me->process(me->x, NULL, me->argc, me->argv);
+ #ifdef DEBUG
+ 			post("soundfiler: process done, locking mutex");
+ #endif
+ 	    
+ 			pthread_mutex_lock(&(soundfiler_queue->mutex));
+ 			pthread_mutex_lock(&(me->mutex));
+ 
+ 			/* freeing the argument vector */
+ 			freebytes(me->argv, sizeof(t_atom) * me->argc); 
+ 
+ 			/* the  process struct */
+ 			next=me->next;
+ 			soundfiler_queue->begin=next;
+ 			freebytes(me, sizeof(t_sfprocess));
+ 		};
+ 		soundfiler_queue->end=NULL;
+     }
+ }
+ 
+ extern int sys_hipriority;   	/* real-time flag, true if priority boosted */
+ 
+ /* create soundfiler thread */
+ void sys_start_sfthread(void)
+ {
+     pthread_attr_t sf_attr;
+     struct sched_param sf_param;
+ 
+ 	int status;
+ 
+ 	//initialize queue
+     soundfiler_queue = getbytes (sizeof(t_sfqueue));
+ 
+     pthread_mutex_init (&soundfiler_queue->mutex,NULL);
+     pthread_cond_init (&soundfiler_queue->cond,NULL);
+ 
+     soundfiler_queue->begin=soundfiler_queue->end=NULL;
+     pthread_mutex_unlock(&(soundfiler_queue->mutex)); 
+     
+     // initialize thread
+     pthread_attr_init(&sf_attr);
+     
+ #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING
+     sf_param.sched_priority=sched_get_priority_min(SCHED_OTHER);
+     pthread_attr_setschedparam(&sf_attr,&sf_param);
+ /*     pthread_attr_setinheritsched(&sf_attr,PTHREAD_EXPLICIT_SCHED); */
+ 
+ #ifdef UNIX
+      if (sys_hipriority == 1)
+      {
+ 		 sf_param.sched_priority=sched_get_priority_min(SCHED_RR);
+ 		 pthread_attr_setschedpolicy(&sf_attr,SCHED_RR);
+      }
+ 	else
+ 	{
+ /* 		pthread_attr_setschedpolicy(&sf_attr,SCHED_OTHER); */
+ /* 		sf_param.sched_priority=sched_get_priority_min(SCHED_OTHER); */
+ 	}
+ #endif /* UNIX */
+ 
+ #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */
+ 
+     //start thread
+     status = pthread_create(&sf_thread_id, &sf_attr, 
+ 							(void *) soundfiler_thread,NULL);
+     if (status != 0)
+ 		error("Couldn't create soundfiler thread: %d",status);
+     else
+ 		post("global soundfiler thread launched, priority: %d", 
+ 			 sf_param.sched_priority);
+ }
+ 
+ static void soundfiler_t_write(t_soundfiler *x, t_symbol *s,
+ 							   int argc, t_atom *argv);
+ 
+ static void soundfiler_t_write_addq(t_soundfiler *x, t_symbol *s,
+ 									int argc, t_atom *argv)
+ {
+     soundfiler_queue_add(soundfiler_t_write,(void *)x,argc, argv);
+ }
+ 
+ static void soundfiler_t_read(t_soundfiler *x, t_symbol *s,
+ 							  int argc, t_atom *argv);
+ 
+ static void soundfiler_t_read_addq(t_soundfiler *x, t_symbol *s,
+ 								   int argc, t_atom *argv)
+ {
+     soundfiler_queue_add(soundfiler_t_read,(void *)x,argc, argv);
+ }
+ 
+ 
+     /* soundfiler_read ...
+     
+     usage: read [flags] filename table ...
+     flags:
+     	-skip <frames> ... frames to skip in file
+ 	-nframes <frames>
+ 	-onset <frames> ... onset in table to read into (NOT DONE YET)
+ 	-raw <headersize channels bytes endian>
+ 	-resize
+ 	-maxsize <max-size>
+ 
+     TB: adapted for threaded use
+     */
+ 
+ static void soundfiler_t_read(t_soundfiler *x, t_symbol *s,
+ 							  int argc, t_atom *argv)
+ {
+     int headersize = -1, channels = 0, bytespersamp = 0, bigendian = 0,
+ 		resize = 0, i, j;
+     long skipframes = 0, 
+ 		nframes = 0, 
+ 		finalsize = 0,                     /* new size */
+ 		itemsleft,
+     	maxsize = DEFMAXSIZE, 
+ 		itemsread = 0, 
+ 		bytelimit  = 0x7fffffff;
+     int fd = -1;
+     char endianness, *filename;
+     t_garray *garrays[MAXSFCHANS];
+     t_float *vecs[MAXSFCHANS];             /* the old array */
+     t_float *nvecs[MAXSFCHANS];            /* the new array */
+     int vecsize[MAXSFCHANS];               /* the old array size */
+     char sampbuf[SAMPBUFSIZE];
+     int bufframes, nitems;
+     FILE *fp;
+ 
+     while (argc > 0 && argv->a_type == A_SYMBOL &&
+ 		   *argv->a_w.w_symbol->s_name == '-')
+     {
+     	char *flag = argv->a_w.w_symbol->s_name + 1;
+ 		if (!strcmp(flag, "skip"))
+ 		{
+ 			if (argc < 2 || argv[1].a_type != A_FLOAT ||
+ 				((skipframes = argv[1].a_w.w_float) < 0))
+ 	    	    goto usage;
+ 			argc -= 2; argv += 2;
+ 		}
+ 		else if (!strcmp(flag, "nframes"))
+ 		{
+ 			if (argc < 2 || argv[1].a_type != A_FLOAT ||
+ 				((nframes = argv[1].a_w.w_float) < 0))
+ 	    	    goto usage;
+ 			argc -= 2; argv += 2;
+ 		}
+ 		else if (!strcmp(flag, "raw"))
+ 		{
+ 			if (argc < 5 ||
+ 				argv[1].a_type != A_FLOAT ||
+ 				((headersize = argv[1].a_w.w_float) < 0) ||
+ 				argv[2].a_type != A_FLOAT ||
+ 				((channels = argv[2].a_w.w_float) < 1) ||
+ 				(channels > MAXSFCHANS) || 
+ 				argv[3].a_type != A_FLOAT ||
+ 				((bytespersamp = argv[3].a_w.w_float) < 2) || 
+ 				(bytespersamp > 4) ||
+ 				argv[4].a_type != A_SYMBOL ||
+ 				((endianness = argv[4].a_w.w_symbol->s_name[0]) != 'b'
+ 				 && endianness != 'l' && endianness != 'n'))
+ 				goto usage;
+ 			if (endianness == 'b')
+ 				bigendian = 1;
+ 			else if (endianness == 'l')
+ 				bigendian = 0;
+ 			else
+ 				bigendian = garray_ambigendian();
+ 			argc -= 5; argv += 5;
+ 		}
+ 		else if (!strcmp(flag, "resize"))
+ 		{
+ 			resize = 1;
+ 			argc -= 1; argv += 1;
+ 		}
+ 		else if (!strcmp(flag, "maxsize"))
+ 		{
+ 			if (argc < 2 || argv[1].a_type != A_FLOAT ||
+ 				((maxsize = argv[1].a_w.w_float) < 0))
+ 	    	    goto usage;
+ 			resize = 1;     /* maxsize implies resize. */
+ 			argc -= 2; argv += 2;
+ 		}
+ 		else goto usage;
+     }
+     if (argc < 2 || argc > MAXSFCHANS + 1 || argv[0].a_type != A_SYMBOL)
+     	goto usage;
+     filename = argv[0].a_w.w_symbol->s_name;
+     argc--; argv++;
+     
+     for (i = 0; i < argc; i++)
+     {
+     	if (argv[i].a_type != A_SYMBOL)
+ 			goto usage;
+ 		if (!(garrays[i] =
+ 			  (t_garray *)pd_findbyclass(argv[i].a_w.w_symbol, garray_class)))
+ 		{
+ 			pd_error(x, "%s: no such table", argv[i].a_w.w_symbol->s_name);
+ 			goto done;
+ 		}
+     	else if (!garray_getfloatarray(garrays[i], &vecsize[i], &vecs[i]))
+     	    error("%s: bad template for tabwrite",
+ 				  argv[i].a_w.w_symbol->s_name);
+     	if (finalsize && finalsize != vecsize[i] && !resize)
+ 		{
+ 			post("soundfiler_read: arrays have different lengths; resizing...");
+ 			resize = 1;
+ 		}
+ 		finalsize = vecsize[i];
+     }
+     fd = open_soundfile(canvas_getdir(x->x_canvas)->s_name, filename,
+ 						headersize, &bytespersamp, &bigendian, &channels, &bytelimit,
+ 						skipframes);
+ 
+     if (fd < 0)
+     {
+ 		pd_error(x, "soundfiler_read: %s: %s", filename, (errno == EIO ?
+ 														  "unknown or bad header format" : strerror(errno)));
+     	goto done;
+     }
+ 
+     if (resize)
+     {
+ 		/* figure out what to resize to */
+     	long poswas, eofis, framesinfile;
+ 	
+ 		poswas = lseek(fd, 0, SEEK_CUR);
+ 		eofis = lseek(fd, 0, SEEK_END);
+ 		if (poswas < 0 || eofis < 0)
+ 		{
+ 			pd_error(x, "lseek failed");
+ 			goto done;
+ 		}
+ 		lseek(fd, poswas, SEEK_SET);
+ 		framesinfile = (eofis - poswas) / (channels * bytespersamp);
+ 		if (framesinfile > maxsize)
+ 		{
+ 			pd_error(x, "soundfiler_read: truncated to %d elements", maxsize);
+ 			framesinfile = maxsize;
+ 		}
+         if (framesinfile > bytelimit / (channels * bytespersamp))
+             framesinfile = bytelimit / (channels * bytespersamp);
+ 		finalsize = framesinfile;
+ 
+     }
+     if (!finalsize) finalsize = 0x7fffffff;
+     if (finalsize > bytelimit / (channels * bytespersamp))
+     	finalsize = bytelimit / (channels * bytespersamp);
+     fp = fdopen(fd, "rb");
+     bufframes = SAMPBUFSIZE / (channels * bytespersamp);
+ 
+ #ifdef SFDEBUG
+     post("buffers: %d", argc);
+     post("channels: %d", channels);
+ #endif
+ 	
+ #ifdef _POSIX_MEMLOCK
+ 	munlockall();
+ #endif
+ 	
+     /* allocate memory for new array */
+ 	if (resize)
+ 		for (i = 0; i < argc; i++)
+ 		{
+ #ifdef SFDEBUG
+ 			post("allocating buffer %d",i);
+ #endif
+ 			nvecs[i]=getalignedbytes (finalsize * sizeof(t_float));
+ 			/* if we are out of memory, free it again and quit */
+ 			if (nvecs[i]==0)
+ 			{
+ 				pd_error(x, "resize failed");
+ 				for (j=0; j!=i;++j)
+ 					/* if the resizing fails, we'll have to free all arrays again */
+ 					freealignedbytes (nvecs[i],finalsize * sizeof(t_float)); 
+ 				goto done;
+ 			}
+ 			/* zero samples */
+ 			if(i > channels)
+ 			{
+ 				memset(nvecs[i],0,vecsize[i] * sizeof(t_float));
+ 			}
+ 		}
+ 	else
+ 		for (i = 0; i < argc; i++)
+ 		{
+ 			nvecs[i] = getalignedbytes (vecsize[i] * sizeof(t_float));
+ 			/* if we are out of memory, free it again and quit */
+ 			if (nvecs[i]==0)
+ 			{
+ 				pd_error(x, "resize failed");
+ 				for (j=0; j!=i;++j)
+ 					/* if the resizing fails, we'll have to free all arrays again */
+ 					freealignedbytes (nvecs[i],vecsize[i] * sizeof(t_float)); 
+ 				goto done;
+ 			}
+ 			/* zero samples */
+ 			if(i > channels)
+ 				memset(nvecs[i],0,vecsize[i] * sizeof(t_float));
+ 		}
+ 
+ 	for (itemsread = 0; itemsread < finalsize; )
+ 	{
+ 		int thisread = finalsize - itemsread;
+ 		thisread = (thisread > bufframes ? bufframes : thisread);
+ 		nitems = fread(sampbuf, channels * bytespersamp, thisread, fp);
+ 		if (nitems <= 0) break;
+ 		soundfile_xferin(channels, argc, nvecs, itemsread,
+ 						 (unsigned char *)sampbuf, nitems, bytespersamp, bigendian);
+ 		itemsread += nitems;
+ 	}
+ 
+ 	/* zero out remaining elements of vectors */
+ 	for (i = 0; i < argc; i++)
+ 	{
+ 		for (j = itemsread; j < finalsize; j++)
+ 			nvecs[i][j] = 0;
+ 	}
+ 
+ 	/* lock the system and reset the garrays */
+ 	sys_lock();
+ 	for (i = 0; i < argc; i++)
+ 	{
+ #ifdef GARRAY_THREAD_LOCK 
+ 		garray_lock(garrays[i]); 
+ #endif
+ 		garrays[i]->x_array.a_vec = (char *) nvecs[i];
+ 		garrays[i]->x_array.a_n = finalsize;
+ #ifdef GARRAY_THREAD_LOCK 
+ 		garray_unlock(garrays[i]); 
+ #endif
+ 		if (garrays[i]->x_usedindsp) canvas_update_dsp();
+ 	}
+ 	sys_unlock();
+ 
+ 	/* do all graphics updates */
+ 	for (i = 0; i < argc; i++)
+ 	{
+ 		t_glist *gl;
+ 		int n = finalsize;
+ 		/* if this is the only array in the graph,
+ 		   reset the graph's coordinates */
+ 		gl = garrays[i]->x_glist;
+ 		if (gl->gl_list == &garrays[i]->x_gobj && !garrays[i]->x_gobj.g_next)
+ 		{
+ 			vmess(&gl->gl_pd, gensym("bounds"), "ffff",
+ 				  0., gl->gl_y1, (double)(n > 1 ? n-1 : 1), gl->gl_y2);
+ 			/* close any dialogs that might have the wrong info now... */
+ 			gfxstub_deleteforkey(gl);
+ 		}
+ 		else garray_redraw(garrays[i]);
+ 	}	
+ 
+  end:
+ 	/* free the old arrays */
+ 	for (i = 0; i < argc; i++)
+ 		freealignedbytes(vecs[i], vecsize[i] * sizeof(t_float));
+ 
+     fclose(fp);
+     fd = -1;
+     goto done;
+  usage:
+     pd_error(x, "usage: read [flags] filename tablename...");
+     post("flags: -skip <n> -nframes <n> -resize -maxsize <n> ...");
+     post("-raw <headerbytes> <channels> <bytespersamp> <endian (b, l, or n)>.");
+  done:
+     if (fd >= 0)
+     	close (fd);
+ #ifdef _POSIX_MEMLOCK
+ 	mlockall(MCL_FUTURE);
+ #endif
+     sys_lock();
+     outlet_float(x->x_obj.ob_outlet, (float)itemsread); 
+     sys_unlock();
+ }
+ 
+     /* this is broken out from soundfiler_write below so garray_write can
+     call it too... not done yet though. */
+ 
+ long soundfiler_t_dowrite(void *obj, t_canvas *canvas,
+     int argc, t_atom *argv)
+ {
+     int headersize, bytespersamp, bigendian,
+     	endianness, swap, filetype, normalize, i, j, nchannels;
+     long onset, nframes, itemsleft,
+     	maxsize = DEFMAXSIZE, itemswritten = 0;
+     t_garray *garrays[MAXSFCHANS];
+     t_float *vecs[MAXSFCHANS];
+     char sampbuf[SAMPBUFSIZE];
+     int bufframes, nitems;
+     int fd = -1;
+     float normfactor, biggest = 0, samplerate;
+     t_symbol *filesym;
+ 
+     if (soundfiler_writeargparse(obj, &argc, &argv, &filesym, &filetype,
+     	&bytespersamp, &swap, &bigendian, &normalize, &onset, &nframes,
+ 	    &samplerate))
+     	    	goto usage;
+     nchannels = argc;
+     if (nchannels < 1 || nchannels > MAXSFCHANS)
+     	goto usage;
+     if (samplerate < 0)
+     	samplerate = sys_getsr();
+     for (i = 0; i < nchannels; i++)
+     {
+     	int vecsize;
+     	if (argv[i].a_type != A_SYMBOL)
+ 	    goto usage;
+ 	if (!(garrays[i] =
+ 	    (t_garray *)pd_findbyclass(argv[i].a_w.w_symbol, garray_class)))
+ 	{
+ 	    pd_error(obj, "%s: no such table", argv[i].a_w.w_symbol->s_name);
+ 	    goto fail;
+ 	}
+     	else if (!garray_getfloatarray(garrays[i], &vecsize, &vecs[i]))
+     	    error("%s: bad template for tabwrite",
+ 	    	argv[i].a_w.w_symbol->s_name);
+     	if (nframes > vecsize - onset)
+ 	    nframes = vecsize - onset;
+     	
+ 	for (j = 0; j < vecsize; j++)
+ 	{
+ 	    if (vecs[i][j] > biggest)
+ 	    	biggest = vecs[i][j];
+ 	    else if (-vecs[i][j] > biggest)
+ 	    	biggest = -vecs[i][j];
+     	}
+     }
+     if (nframes <= 0)
+     {
+ 	pd_error(obj, "soundfiler_write: no samples at onset %ld", onset);
+     	goto fail;
+     }
+ 
+     if ((fd = create_soundfile(canvas, filesym->s_name, filetype,
+     	nframes, bytespersamp, bigendian, nchannels,
+ 	    swap, samplerate)) < 0)
+     {
+     	post("%s: %s\n", filesym->s_name, strerror(errno));
+     	goto fail;
+     }
+     if (!normalize)
+     {
+     	if ((bytespersamp != 4) && (biggest > 1))
+ 	{
+     	    post("%s: normalizing max amplitude %f to 1", filesym->s_name, biggest);
+     	    normalize = 1;
+     	}
+ 	else post("%s: biggest amplitude = %f", filesym->s_name, biggest);
+     }
+     if (normalize)
+ 	normfactor = (biggest > 0 ? 32767./(32768. * biggest) : 1);
+     else normfactor = 1;
+ 
+     bufframes = SAMPBUFSIZE / (nchannels * bytespersamp);
+ 
+     for (itemswritten = 0; itemswritten < nframes; )
+     {
+     	int thiswrite = nframes - itemswritten, nitems, nbytes;
+     	thiswrite = (thiswrite > bufframes ? bufframes : thiswrite);
+ 	soundfile_xferout(argc, vecs, (unsigned char *)sampbuf, thiswrite,
+ 	    onset, bytespersamp, bigendian, normfactor);
+     	nbytes = write(fd, sampbuf, nchannels * bytespersamp * thiswrite);
+ 	if (nbytes < nchannels * bytespersamp * thiswrite)
+ 	{
+ 	    post("%s: %s", filesym->s_name, strerror(errno));
+ 	    if (nbytes > 0)
+ 	    	itemswritten += nbytes / (nchannels * bytespersamp);
+ 	    break;
+ 	}
+ 	itemswritten += thiswrite;
+ 	onset += thiswrite;
+     }
+     if (fd >= 0)
+     {
+     	soundfile_finishwrite(obj, filesym->s_name, fd,
+     	    filetype, nframes, itemswritten, nchannels * bytespersamp, swap);
+     	close (fd);
+     }
+     return ((float)itemswritten); 
+ usage:
+     pd_error(obj, "usage: write [flags] filename tablename...");
+     post("flags: -skip <n> -nframes <n> -bytes <n> -wave -aiff -nextstep ...");
+     post("-big -little -normalize");
+     post("(defaults to a 16-bit wave file).");
+ fail:
+     if (fd >= 0)
+     	close (fd);
+     return (0); 
+ } 
+ 
+ static void soundfiler_t_write(t_soundfiler *x, t_symbol *s,
+     int argc, t_atom *argv)
+ {
+     long bozo = soundfiler_t_dowrite(x, x->x_canvas,
+     	argc, argv);
+     sys_lock();
+     outlet_float(x->x_obj.ob_outlet, (float)bozo); 
+     sys_lock();
+ }
+ 
+ static void soundfiler_t_resize(t_soundfiler *x, t_symbol *s,
+ 				int argc, t_atom *argv);
+ 
+ static void soundfiler_t_resize_addq(t_soundfiler *x, t_symbol *s,
+     int argc, t_atom *argv)
+ {
+     soundfiler_queue_add(soundfiler_t_resize,(void *)x,argc, argv);
+ }
+ 
+ 
+     /* TB: soundfiler_t_resize ...
+     usage: resize table size
+     adapted from garray_resize
+     */
+ static void soundfiler_t_resize(t_soundfiler *y, t_symbol *s,
+ 								int argc, t_atom *argv)
+ {
+     int was, elemsize;       /* array contains was elements of size elemsize */
+     t_float * vec;           /* old array */ 
+     t_glist *gl;
+     int dspwas;
+     int n;                   /* resize of n elements */
+     char *nvec;              /* new array */ 
+ 
+     t_garray * x = (t_garray *)pd_findbyclass(argv[0].a_w.w_symbol, garray_class);
+ 
+     if (!(x))
+     {
+ 		pd_error(y, "%s: no such table", argv[0].a_w.w_symbol->s_name);
+ 		goto usage;
+     }
+     
+     vec = (t_float*) x->x_array.a_vec;
+     was = x->x_array.a_n;
+ 
+     if ((argv+1)->a_type == A_FLOAT)
+     {
+ 		n = (int) (argv+1)->a_w.w_float;
+     }
+     else
+     {
+ 		goto usage;
+     }
+ 
+     if (n == was)
+     {
+ 		return;
+     }
+ 
+     if (n < 1) n = 1;
+     elemsize = template_findbyname(x->x_array.a_templatesym)->t_n * sizeof(t_word);
+ 
+ #ifdef _POSIX_MEMLOCK
+ 		munlockall();
+ #endif
+     if (was > n)
+     {
+ 		nvec = copyalignedbytes(x->x_array.a_vec, was * elemsize);
+     }
+     else
+     {
+ 		nvec = getalignedbytes(n * elemsize);
+ 		memcpy (nvec, x->x_array.a_vec, was * elemsize);
+ 	
+ 		/* LATER should check t_resizebytes result */
+ 		memset(nvec + was*elemsize,
+ 			   0, (n - was) * elemsize);
+     }
+     if (!nvec)
+     {
+     	pd_error(x, "array resize failed: out of memory");
+ #ifdef _POSIX_MEMLOCK
+ 		mlockall(MCL_FUTURE);
+ #endif
+ 		return;
+     }
+ 
+ 
+     /* TB: we'll have to be sure that no one is accessing the array */
+     sys_lock();
+ #ifdef GARRAY_THREAD_LOCK 
+     garray_lock(x); 
+ #endif
+     x->x_array.a_vec = nvec;
+     x->x_array.a_n = n;
+ #ifdef GARRAY_THREAD_LOCK 
+     garray_unlock(x); 
+ #endif
+     if (x->x_usedindsp) canvas_update_dsp();
+     sys_unlock();
+ 
+     
+ 	/* if this is the only array in the graph,
+ 	   reset the graph's coordinates */
+     gl = x->x_glist;
+     if (gl->gl_list == &x->x_gobj && !x->x_gobj.g_next)
+     {
+     	vmess(&gl->gl_pd, gensym("bounds"), "ffff",
+ 			  0., gl->gl_y1, (double)(n > 1 ? n-1 : 1), gl->gl_y2);
+ 		/* close any dialogs that might have the wrong info now... */
+     	gfxstub_deleteforkey(gl);
+     }
+     else garray_redraw(x);
+ 
+     freealignedbytes (vec, was * elemsize);
+ #ifdef _POSIX_MEMLOCK
+ 	mlockall(MCL_FUTURE);
+ #endif
+     sys_lock();
+     outlet_float(y->x_obj.ob_outlet, (float)atom_getintarg(1,argc,argv)); 
+     sys_unlock();
+     return;
+     
+  usage:
+     pd_error(x, "usage: resize tablename size");
+ }
+ 
+ 
+ static void soundfiler_t_const(t_soundfiler *x, t_symbol *s,
+ 				int argc, t_atom *argv);
+ 
+ static void soundfiler_t_const_addq(t_soundfiler *x, t_symbol *s,
+     int argc, t_atom *argv)
+ {
+     soundfiler_queue_add(soundfiler_t_const,(void *)x,argc, argv);
+ }
+ 
+ 
+ /* TB: soundfiler_t_const ...
+    usage: const table value
+ */
+ static void soundfiler_t_const(t_soundfiler *y, t_symbol *s,
+ 							   int argc, t_atom *argv)
+ {
+     int size, elemsize;    /* array contains was elements of size elemsize */
+     t_float * vec;         /* old array */ 
+     t_glist *gl;
+     int dspwas;
+     int val;               /* value */
+     char *nvec;            /* new array */ 
+     int i;
+ 
+     t_garray * x = (t_garray *)pd_findbyclass(argv[0].a_w.w_symbol, garray_class);
+ 
+     if (!(x))
+     {
+ 		pd_error(y, "%s: no such table", argv[0].a_w.w_symbol->s_name);
+ 		goto usage;
+     }
+     
+ 
+ 
+     vec = (t_float*) x->x_array.a_vec;
+     size = x->x_array.a_n;
+     
+     if ((argv+1)->a_type == A_FLOAT)
+     {
+ 		val = (int) (argv+1)->a_w.w_float;
+     }
+     else
+     {
+ 		goto usage;
+     }
+ 
+     elemsize = template_findbyname(x->x_array.a_templatesym)->t_n * sizeof(t_word);
+     
+ 
+     /* allocating memory */
+ #ifdef _POSIX_MEMLOCK
+     munlockall();
+ #endif
+     nvec = getalignedbytes(size * elemsize);
+ 
+     if (!nvec)
+     {
+     	pd_error(x, "array resize failed: out of memory");
+ #ifdef _POSIX_MEMLOCK
+ 		mlockall(MCL_FUTURE);
+ #endif
+ 		return;
+     }
+     
+     /* setting array */
+     for (i=0; i!=size; ++i)
+     {
+ 		nvec[i]=val;
+     }
+ 
+     /* TB: we'll have to be sure that no one is accessing the array */
+     sys_lock();
+ #ifdef GARRAY_THREAD_LOCK 
+     garray_lock(x); 
+ #endif
+     x->x_array.a_vec = nvec;
+ #ifdef GARRAY_THREAD_LOCK 
+     garray_unlock(x); 
+ #endif
+     if (x->x_usedindsp) canvas_update_dsp();
+     sys_unlock();
+ 
+     
+ 	/* if this is the only array in the graph,
+ 	   reset the graph's coordinates */
+     gl = x->x_glist;
+     if (gl->gl_list == &x->x_gobj && !x->x_gobj.g_next)
+     {
+     	vmess(&gl->gl_pd, gensym("bounds"), "ffff",
+ 			  0., gl->gl_y1, (double)(size > 1 ? size-1 : 1), gl->gl_y2);
+ 		/* close any dialogs that might have the wrong info now... */
+     	gfxstub_deleteforkey(gl);
+     }
+     else garray_redraw(x);
+ 
+     freealignedbytes (vec, size * elemsize);
+ #ifdef _POSIX_MEMLOCK
+     mlockall(MCL_FUTURE);
+ #endif
+     sys_lock();
+ 	outlet_float(y->x_obj.ob_outlet, size); 
+     sys_unlock();
+     return;
+     
+  usage:
+     pd_error(x, "usage: const tablename value");
+ }
+ 
+ 
+ #endif /* THREADED_SF */
+ 
+ 
+ 
  static t_soundfiler *soundfiler_new(void)
  {
***************
*** 903,906 ****
--- 1768,1774 ----
      x->x_canvas = canvas_getcurrent();
      outlet_new(&x->x_obj, &s_float);
+ #ifdef THREADED_SF
+     post("warning: threaded soundfiler is not synchronous");
+ #endif /* THREADED_SF */
      return (x);
  }
***************
*** 1240,1247 ****
--- 2108,2126 ----
      soundfiler_class = class_new(gensym("soundfiler"), (t_newmethod)soundfiler_new, 
          0, sizeof(t_soundfiler), 0, 0);
+ #ifdef THREADED_SF
+     class_addmethod(soundfiler_class, (t_method)soundfiler_t_read_addq, 
+ 		    gensym("read"), A_GIMME, 0);
+     class_addmethod(soundfiler_class, (t_method)soundfiler_t_write_addq,
+ 		    gensym("write"), A_GIMME, 0);
+     class_addmethod(soundfiler_class, (t_method)soundfiler_t_resize_addq,
+ 		    gensym("resize"), A_GIMME, 0);
+     class_addmethod(soundfiler_class, (t_method)soundfiler_t_const_addq,
+ 		    gensym("const"), A_GIMME, 0);
+ #else
      class_addmethod(soundfiler_class, (t_method)soundfiler_read, gensym("read"), 
          A_GIMME, 0);
      class_addmethod(soundfiler_class, (t_method)soundfiler_write,
          gensym("write"), A_GIMME, 0);
+ #endif /* THREADED_SF */
  }
  

Index: d_fft.c
===================================================================
RCS file: /cvsroot/pure-data/pd/src/d_fft.c,v
retrieving revision 1.2
retrieving revision 1.2.4.1
diff -C2 -d -r1.2 -r1.2.4.1
*** d_fft.c	6 Sep 2004 20:20:33 -0000	1.2
--- d_fft.c	5 Nov 2004 13:55:58 -0000	1.2.4.1
***************
*** 5,8 ****
--- 5,14 ----
  #include "m_pd.h"
  
+ #ifdef HAVE_LIBFFTW3F
+ #include "fftw3.h"
+ #include <string.h>
+ #endif
+ 
+ #ifndef HAVE_LIBFFTW3F
  /* ------------------------ fft~ and ifft~ -------------------------------- */
  static t_class *sigfft_class, *sigifft_class;
***************
*** 40,47 ****
      int n = w[3];
      for (;n--; in1++, in2++)
!     {   
          float f = *in1;
!         *in1 = *in2;
!         *in2 = f;
      }
      return (w+4);    
--- 46,53 ----
      int n = w[3];
      for (;n--; in1++, in2++)
!     {	
          float f = *in1;
! 	*in1 = *in2;
! 	*in2 = f;
      }
      return (w+4);    
***************
*** 74,87 ****
      float *out2 = sp[3]->s_vec;
      if (out1 == in2 && out2 == in1)
!         dsp_add(sigfft_swap, 3, out1, out2, n);
      else if (out1 == in2)
      {
!         dsp_add(copy_perform, 3, in2, out2, n);
!         dsp_add(copy_perform, 3, in1, out1, n);
      }
      else
      {
!         if (out1 != in1) dsp_add(copy_perform, 3, in1, out1, n);
!         if (out2 != in2) dsp_add(copy_perform, 3, in2, out2, n);
      }
      dsp_add(f, 3, sp[2]->s_vec, sp[3]->s_vec, n);
--- 80,93 ----
      float *out2 = sp[3]->s_vec;
      if (out1 == in2 && out2 == in1)
!     	dsp_add(sigfft_swap, 3, out1, out2, n);
      else if (out1 == in2)
      {
!     	dsp_add(copy_perform, 3, in2, out2, n);
!     	dsp_add(copy_perform, 3, in1, out1, n);
      }
      else
      {
!     	if (out1 != in1) dsp_add(copy_perform, 3, in1, out1, n);
!     	if (out2 != in2) dsp_add(copy_perform, 3, in2, out2, n);
      }
      dsp_add(f, 3, sp[2]->s_vec, sp[3]->s_vec, n);
***************
*** 101,110 ****
  {
      sigfft_class = class_new(gensym("fft~"), sigfft_new, 0,
!         sizeof(t_sigfft), 0, 0);
      CLASS_MAINSIGNALIN(sigfft_class, t_sigfft, x_f);
      class_addmethod(sigfft_class, (t_method)sigfft_dsp, gensym("dsp"), 0);
  
      sigifft_class = class_new(gensym("ifft~"), sigifft_new, 0,
!         sizeof(t_sigfft), 0, 0);
      CLASS_MAINSIGNALIN(sigifft_class, t_sigfft, x_f);
      class_addmethod(sigifft_class, (t_method)sigifft_dsp, gensym("dsp"), 0);
--- 107,116 ----
  {
      sigfft_class = class_new(gensym("fft~"), sigfft_new, 0,
!     	sizeof(t_sigfft), 0, 0);
      CLASS_MAINSIGNALIN(sigfft_class, t_sigfft, x_f);
      class_addmethod(sigfft_class, (t_method)sigfft_dsp, gensym("dsp"), 0);
  
      sigifft_class = class_new(gensym("ifft~"), sigifft_new, 0,
!     	sizeof(t_sigfft), 0, 0);
      CLASS_MAINSIGNALIN(sigifft_class, t_sigfft, x_f);
      class_addmethod(sigifft_class, (t_method)sigifft_dsp, gensym("dsp"), 0);
***************
*** 137,144 ****
      int n = w[3];
      while (n--) *(--out) = *in++;
!     *(--out) = 0;                   /* to hell with it */
      return (w+4);
  }
  
  static t_int *sigrfft_perform(t_int *w)
  {
--- 143,151 ----
      int n = w[3];
      while (n--) *(--out) = *in++;
!     *(--out) = 0;	    	    /* to hell with it */
      return (w+4);
  }
  
+ 
  static t_int *sigrfft_perform(t_int *w)
  {
***************
*** 157,174 ****
      if (n < 4)
      {
!         error("fft: minimum 4 points");
!         return;
      }
!     if (in1 == out2)    /* this probably never happens */
      {
!         dsp_add(sigrfft_perform, 2, out2, n);
!         dsp_add(copy_perform, 3, out2, out1, n2);
!         dsp_add(sigrfft_flip, 3, out2 + (n2+1), out2 + n2, n2-1);
      }
      else
      {
!         if (in1 != out1) dsp_add(copy_perform, 3, in1, out1, n);
!         dsp_add(sigrfft_perform, 2, out1, n);
!         dsp_add(sigrfft_flip, 3, out1 + (n2+1), out2 + n2, n2-1);
      }
      dsp_add_zero(out1 + n2, n2);
--- 164,181 ----
      if (n < 4)
      {
!     	error("fft: minimum 4 points");
!     	return;
      }
!     if (in1 == out2)	/* this probably never happens */
      {
!     	dsp_add(sigrfft_perform, 2, out2, n);
!     	dsp_add(copy_perform, 3, out2, out1, n2);
!     	dsp_add(sigrfft_flip, 3, out2 + (n2+1), out2 + n2, n2-1);
      }
      else
      {
!     	if (in1 != out1) dsp_add(copy_perform, 3, in1, out1, n);
!     	dsp_add(sigrfft_perform, 2, out1, n);
!     	dsp_add(sigrfft_flip, 3, out1 + (n2+1), out2 + n2, n2-1);
      }
      dsp_add_zero(out1 + n2, n2);
***************
*** 179,183 ****
  {
      sigrfft_class = class_new(gensym("rfft~"), sigrfft_new, 0,
!         sizeof(t_sigrfft), 0, 0);
      CLASS_MAINSIGNALIN(sigrfft_class, t_sigrfft, x_f);
      class_addmethod(sigrfft_class, (t_method)sigrfft_dsp, gensym("dsp"), 0);
--- 186,190 ----
  {
      sigrfft_class = class_new(gensym("rfft~"), sigrfft_new, 0,
!     	sizeof(t_sigrfft), 0, 0);
      CLASS_MAINSIGNALIN(sigrfft_class, t_sigrfft, x_f);
      class_addmethod(sigrfft_class, (t_method)sigrfft_dsp, gensym("dsp"), 0);
***************
*** 185,190 ****
--- 192,200 ----
  }
  
+ 
  /* ----------------------- rifft~ -------------------------------- */
  
+ 
+ 
  static t_class *sigrifft_class;
  
***************
*** 220,235 ****
      if (n < 4)
      {
!         error("fft: minimum 4 points");
!         return;
      }
      if (in2 == out1)
      {
!         dsp_add(sigrfft_flip, 3, out1+1, out1 + n, (n2-1));
!         dsp_add(copy_perform, 3, in1, out1, n2);
      }
      else
      {
!         if (in1 != out1) dsp_add(copy_perform, 3, in1, out1, n2);
!         dsp_add(sigrfft_flip, 3, in2+1, out1 + n, n2-1);
      }
      dsp_add(sigrifft_perform, 2, out1, n);
--- 230,245 ----
      if (n < 4)
      {
!     	error("fft: minimum 4 points");
!     	return;
      }
      if (in2 == out1)
      {
!     	dsp_add(sigrfft_flip, 3, out1+1, out1 + n, (n2-1));
!     	dsp_add(copy_perform, 3, in1, out1, n2);
      }
      else
      {
!     	if (in1 != out1) dsp_add(copy_perform, 3, in1, out1, n2);
!     	dsp_add(sigrfft_flip, 3, in2+1, out1 + n, n2-1);
      }
      dsp_add(sigrifft_perform, 2, out1, n);
***************
*** 239,243 ****
  {
      sigrifft_class = class_new(gensym("rifft~"), sigrifft_new, 0,
!         sizeof(t_sigrifft), 0, 0);
      CLASS_MAINSIGNALIN(sigrifft_class, t_sigrifft, x_f);
      class_addmethod(sigrifft_class, (t_method)sigrifft_dsp, gensym("dsp"), 0);
--- 249,253 ----
  {
      sigrifft_class = class_new(gensym("rifft~"), sigrifft_new, 0,
!     	sizeof(t_sigrifft), 0, 0);
      CLASS_MAINSIGNALIN(sigrifft_class, t_sigrifft, x_f);
      class_addmethod(sigrifft_class, (t_method)sigrifft_dsp, gensym("dsp"), 0);
***************
*** 245,248 ****
--- 255,511 ----
  }
  
+ #else
+ 
+ /* Support for fftw3 by Tim Blechmann                                       */
+ 
+ /* ------------------------ fft~ and ifft~ -------------------------------- */
+ 
+ static t_class *sigfftw_class, *sigifftw_class;
+ 
+ typedef struct fftw
+ {
+     t_object x_obj;
+     float x_f;
+ 
+     fftwf_plan plan;
+     fftwf_iodim dim;
+ } t_sigfftw;
+ 
+ static void *sigfftw_new(void)
+ {
+     t_sigfftw *x = (t_sigfftw *)pd_new(sigfftw_class);
+     outlet_new(&x->x_obj, gensym("signal"));
+     outlet_new(&x->x_obj, gensym("signal"));
+     inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal);
+     x->x_f = 0;
+     return (x);
+ }
+ 
+ static void sigfftw_free(t_sigfftw * x)
+ {
+     fftwf_destroy_plan(x->plan);
+ }
+ 
+ static t_int *sigfftw_perform(t_int *w)
+ {
+     fftwf_execute(*(fftwf_plan *)w[1]);
+ 
+     return (w+2);
+ }
+ 
+ static void sigfftw_dsp(t_sigfftw *x, t_signal **sp)
+ {
+     int n = sp[0]->s_n;
+     float *in1 = sp[0]->s_vec;
+     float *in2 = sp[1]->s_vec;
+     float *out1 = sp[2]->s_vec;
+     float *out2 = sp[3]->s_vec;
+     
+     x->dim.n=n;
+     x->dim.is=1;
+     x->dim.os=1;
+     x->plan = fftwf_plan_guru_split_dft(1, &(x->dim), 0, NULL, in1, 
+ 					in2, out1, out2, FFTW_MEASURE);
+     dsp_add(sigfftw_perform, 1, &x->plan);
+ }
+ 
+ static void sigifftw_dsp(t_sigfftw *x, t_signal **sp)
+ {
+     int n = sp[0]->s_n;
+     float *in1 = sp[0]->s_vec;
+     float *in2 = sp[1]->s_vec;
+     float *out1 = sp[2]->s_vec;
+     float *out2 = sp[3]->s_vec;
+     
+     x->dim.n=n;
+     x->dim.is=1;
+     x->dim.os=1;
+     x->plan = fftwf_plan_guru_split_dft(1, &(x->dim), 0, NULL, in2, 
+ 					in1, out2, out1, FFTW_MEASURE);
+     dsp_add(sigfftw_perform, 1, &x->plan);
+ }
+ 
+ static void sigfftw_setup(void)
+ {
+     sigfftw_class = class_new(gensym("fft~"), sigfftw_new, 
+ 			      (t_method) sigfftw_free,
+ 			      sizeof(t_sigfftw), 0, 0);
+     CLASS_MAINSIGNALIN(sigfftw_class, t_sigfftw, x_f);
+     class_addmethod(sigfftw_class, (t_method)sigfftw_dsp, 
+ 		    gensym("dsp"), 0);
+ 
+     sigifftw_class = class_new(gensym("ifft~"), sigfftw_new, 
+ 			       (t_method) sigfftw_free, 
+ 			       sizeof(t_sigfftw), 0, 0);
+     CLASS_MAINSIGNALIN(sigifftw_class, t_sigfftw, x_f);
+     class_addmethod(sigifftw_class, (t_method)sigifftw_dsp, 
+ 		    gensym("dsp"), 0);
+     class_sethelpsymbol(sigifftw_class, gensym("fft~"));
+ 
+ }
+ 
+ 
+ /* ----------------------- rfft~ --------------------------------- */
+ 
+ static t_class *sigrfftw_class;
+ 
+ typedef struct rfftw
+ {
+     t_object x_obj;
+     float x_f;
+     
+     fftwf_plan plan;  
+     fftwf_iodim dim;
+ } t_sigrfftw;
+ 
+ static void *sigrfftw_new(void)
+ {
+     t_sigrfftw *x = (t_sigrfftw *)pd_new(sigrfftw_class);
+     outlet_new(&x->x_obj, gensym("signal"));
+     outlet_new(&x->x_obj, gensym("signal"));
+     x->x_f = 0;
+     return (x);
+ }
+ 
+ static void sigrfftw_free(t_sigrfftw *x)
+ {
+     fftwf_destroy_plan(x->plan);
+ }
+ 
+ /*
+  * for compatibility reasons with the mayer fft, we'll have to invert 
+  * some samples ... this is ugly, but someone might rely on that ...
+  */
+ static void sigrfftw_invert(t_sample * s, t_int n)
+ {
+     while (n!=0)
+     {
+ 	--n;
+ 	s[n]=-s[n];
+     }
+ }
+ 
+ static t_int *sigrfftw_perform(t_int *w)
+ {
+     fftwf_execute(*(fftwf_plan*)w[1]);
+     sigrfftw_invert((t_sample*)w[2],(t_int)w[3]);
+ 
+     return (w+4);
+ }
+ 
+ static void sigrfftw_dsp(t_sigrfftw *x, t_signal **sp)
+ {
+     int n = sp[0]->s_n, n2 = (n>>1);
+     float *in = sp[0]->s_vec;
+     float *out1 = sp[1]->s_vec;
+     float *out2 = sp[2]->s_vec;
+ 
+     if (n < 4)
+     {
+     	error("fft: minimum 4 points");
+     	return;
+     }
+     else    
+     {
+ 	x->dim.n=n;
+ 	x->dim.is=1;
+ 	x->dim.os=1;
+ 	x->plan = fftwf_plan_guru_split_dft_r2c(1, &(x->dim), 0, NULL, 
+ 						in, out1, out2,
+ 						FFTW_MEASURE);
+ 	dsp_add(sigrfftw_perform,3,&x->plan,out2+1,n2-1);
+     }
+ 
+     dsp_add_zero(out1 + n2, n2);
+     dsp_add_zero(out2 + n2, n2);
+ }
+ 
+ static void sigrfftw_setup(void)
+ {
+     sigrfftw_class = class_new(gensym("rfft~"), sigrfftw_new, 
+ 			       (t_method)sigrfftw_free,
+ 			       sizeof(t_sigrfftw), 0, 0);
+     CLASS_MAINSIGNALIN(sigrfftw_class, t_sigrfftw, x_f);
+     class_addmethod(sigrfftw_class, (t_method)sigrfftw_dsp, 
+ 		    gensym("dsp"), 0);
+     class_sethelpsymbol(sigrfftw_class, gensym("fft~"));
+ }
+ 
+ 
+ /* ----------------------- rifft~ -------------------------------- */
+ 
+ static t_class *sigrifftw_class;
+ 
+ typedef struct rifftw
+ {
+     t_object x_obj;   
+     float x_f;
+ 
+     fftwf_plan plan;  
+     fftwf_iodim dim;
+ } t_sigrifftw;
+ 
+ static void *sigrifftw_new(void)
+ {
+     t_sigrifftw *x = (t_sigrifftw *)pd_new(sigrifftw_class);
+     inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal);
+     outlet_new(&x->x_obj, gensym("signal"));
+     x->x_f = 0;
+     return (x);
+ }
+ 
+ static void sigrifftw_free(t_sigrifftw *x)
+ {
+     fftwf_destroy_plan(x->plan);
+ }
+ 
+ static t_int *sigrifftw_perform(t_int *w)
+ {
+     sigrfftw_invert((t_sample *)w[2],w[3]); 
+     fftwf_execute(*(fftwf_plan*)w[1]);
+     
+     return (w+4);
+ }
+ 
+ static void sigrifftw_dsp(t_sigrifftw *x, t_signal **sp)
+ {
+     int n = sp[0]->s_n, n2 = (n>>1);
+     float *in1 = sp[0]->s_vec;
+     float *in2 = sp[1]->s_vec;
+     float *out = sp[2]->s_vec;
+ 
+     if (n < 4)
+     {
+     	error("fft: minimum 4 points");
+     	return;
+     }
+ 
+     else    
+     {
+ 	x->dim.n=n;
+ 	x->dim.is=1;
+ 	x->dim.os=1;
+ 	x->plan = fftwf_plan_guru_split_dft_c2r(1, &(x->dim), 0, NULL, 
+ 						in1, in2, out,
+ 						FFTW_MEASURE);
+ 	dsp_add(sigrifftw_perform,3,&x->plan,in2,n2);
+     }
+ }
+ 
+ static void sigrifftw_setup(void)
+ {
+     sigrifftw_class = class_new(gensym("rifft~"), sigrifftw_new, 
+ 				(t_method)sigrifftw_free,
+ 				sizeof(t_sigrifftw), 0, 0);
+     CLASS_MAINSIGNALIN(sigrifftw_class, t_sigrifftw, x_f);
+     class_addmethod(sigrifftw_class, (t_method)sigrifftw_dsp, 
+ 		    gensym("dsp"), 0);
+     class_sethelpsymbol(sigrifftw_class, gensym("fft~"));
+ }
+ 
+ #endif /* HAVE_LIBFFTW3F */
+ /* end of FFTW support                                             */
+ 
+ 
  /* ----------------------- framp~ -------------------------------- */
  
***************
*** 283,307 ****
      while (n--)
      {
!         float re, im, pow, freq;
!         lastreal = currentreal;
!         currentreal = nextreal;
!         nextreal = *inreal++;
!         lastimag = currentimag;
!         currentimag = nextimag;
!         nextimag = *inimag++;
!         re = currentreal - 0.5f * (lastreal + nextreal);
!         im = currentimag - 0.5f * (lastimag + nextimag);
!         pow = re * re + im * im;
!         if (pow > 1e-19)
!         {
!             float detune = ((lastreal - nextreal) * re +
!                     (lastimag - nextimag) * im) / (2.0f * pow);
!             if (detune > 2 || detune < -2) freq = pow = 0;
!             else freq = fbin + detune;
!         }
!         else freq = pow = 0;
!         *outfreq++ = freq;
!         *outamp++ = oneovern2 * pow;
!         fbin += 1.0f;
      }
      while (m--) *outamp++ = *outfreq++ = 0;
--- 546,570 ----
      while (n--)
      {
!     	float re, im, pow, freq;
!     	lastreal = currentreal;
!     	currentreal = nextreal;
!     	nextreal = *inreal++;
!     	lastimag = currentimag;
!     	currentimag = nextimag;
!     	nextimag = *inimag++;
!     	re = currentreal - 0.5f * (lastreal + nextreal);
!     	im = currentimag - 0.5f * (lastimag + nextimag);
!     	pow = re * re + im * im;
!     	if (pow > 1e-19)
!     	{
!     	    float detune = ((lastreal - nextreal) * re +
!     	    	    (lastimag - nextimag) * im) / (2.0f * pow);
!     	    if (detune > 2 || detune < -2) freq = pow = 0;
!     	    else freq = fbin + detune;
!     	}
!     	else freq = pow = 0;
!     	*outfreq++ = freq;
!     	*outamp++ = oneovern2 * pow;
!     	fbin += 1.0f;
      }
      while (m--) *outamp++ = *outfreq++ = 0;
***************
*** 316,324 ****
      if (n < 4)
      {
!         error("framp: minimum 4 points");
!         return;
      }
      dsp_add(sigframp_perform, 5, sp[0]->s_vec, sp[1]->s_vec,
!         sp[2]->s_vec, sp[3]->s_vec, n2);
      dsp_add(sigsqrt_perform, 3, sp[3]->s_vec, sp[3]->s_vec, n2);
  }
--- 579,587 ----
      if (n < 4)
      {
!     	error("framp: minimum 4 points");
!     	return;
      }
      dsp_add(sigframp_perform, 5, sp[0]->s_vec, sp[1]->s_vec,
!     	sp[2]->s_vec, sp[3]->s_vec, n2);
      dsp_add(sigsqrt_perform, 3, sp[3]->s_vec, sp[3]->s_vec, n2);
  }
***************
*** 327,331 ****
  {
      sigframp_class = class_new(gensym("framp~"), sigframp_new, 0,
!         sizeof(t_sigframp), 0, 0);
      CLASS_MAINSIGNALIN(sigframp_class, t_sigframp, x_f);
      class_addmethod(sigframp_class, (t_method)sigframp_dsp, gensym("dsp"), 0);
--- 590,594 ----
  {
      sigframp_class = class_new(gensym("framp~"), sigframp_new, 0,
!     	sizeof(t_sigframp), 0, 0);
      CLASS_MAINSIGNALIN(sigframp_class, t_sigframp, x_f);
      class_addmethod(sigframp_class, (t_method)sigframp_dsp, gensym("dsp"), 0);
***************
*** 336,342 ****
  void d_fft_setup(void)
  {
      sigfft_setup();
      sigrfft_setup();
      sigrifft_setup();
!     sigframp_setup();
  }
--- 599,613 ----
  void d_fft_setup(void)
  {
+     sigframp_setup();
+ 
+ #ifndef HAVE_LIBFFTW3F
      sigfft_setup();
      sigrfft_setup();
      sigrifft_setup();
! #else
!     sigfftw_setup();     /* added by Tim Blechmann to support fftw */
!     sigrifftw_setup();
!     sigrfftw_setup();
! #endif /* HAVE_LIBFFTW3F */
! 
  }

Index: d_ugen.c
===================================================================
RCS file: /cvsroot/pure-data/pd/src/d_ugen.c,v
retrieving revision 1.3
retrieving revision 1.3.4.1
diff -C2 -d -r1.3 -r1.3.4.1
*** d_ugen.c	6 Sep 2004 20:20:33 -0000	1.3
--- d_ugen.c	5 Nov 2004 13:55:58 -0000	1.3.4.1
***************
*** 28,31 ****
--- 28,35 ----
  #include <stdarg.h>
  
+ 
+ /* T.Grill - include SIMD functionality */
+ #include "m_simd.h"
+ 
  extern t_class *vinlet_class, *voutlet_class, *canvas_class;
  t_sample *obj_findsignalscalar(t_object *x, int m);
***************
*** 75,80 ****
      if (n&7)
          dsp_add(zero_perform, 2, out, n);
!     else        
!         dsp_add(zero_perf8, 2, out, n);
  }
  
--- 79,87 ----
      if (n&7)
          dsp_add(zero_perform, 2, out, n);
!     else 
! 		if(SIMD_CHECK1(n,out))
! 			dsp_add(zero_perf_simd, 2, out, n);
! 		else        
! 			dsp_add(zero_perf8, 2, out, n);
  }
  
***************
*** 336,341 ****
      {
          signal_usedlist = sig->s_nextused;
!         if (!sig->s_isborrowed)
              t_freebytes(sig->s_vec, sig->s_n * sizeof (*sig->s_vec));
          t_freebytes(sig, sizeof *sig);
      }
--- 343,354 ----
      {
          signal_usedlist = sig->s_nextused;
! 		if (!sig->s_isborrowed) 
! 		{
! #ifndef VECTORALIGNMENT
              t_freebytes(sig->s_vec, sig->s_n * sizeof (*sig->s_vec));
+ #else
+             freealignedbytes(sig->s_vec, sig->s_n * sizeof (*sig->s_vec));
+ #endif
+ 		}
          t_freebytes(sig, sizeof *sig);
      }
***************
*** 422,426 ****
--- 435,444 ----
          if (n)
          {
+ #ifndef VECTORALIGNMENT
              ret->s_vec = (t_sample *)getbytes(n * sizeof (*ret->s_vec));
+ #else
+ 		    /* T.Grill - make signal vectors aligned! */
+             ret->s_vec = (t_sample *)getalignedbytes(n * sizeof (*ret->s_vec));
+ #endif
              ret->s_isborrowed = 0;
          }

Index: d_math.c
===================================================================
RCS file: /cvsroot/pure-data/pd/src/d_math.c,v
retrieving revision 1.2
retrieving revision 1.2.4.1
diff -C2 -d -r1.2 -r1.2.4.1
*** d_math.c	6 Sep 2004 20:20:33 -0000	1.2
--- d_math.c	5 Nov 2004 13:55:58 -0000	1.2.4.1
***************
*** 11,14 ****
--- 11,17 ----
  #define LOGTEN 2.302585092994
  
+ /* T.Grill - use SIMD functionality */
+ #include "m_simd.h"
+ 
  /* ------------------------- clip~ -------------------------- */
  static t_class *clip_class;
***************
*** 34,56 ****
  }
  
  static t_int *clip_perform(t_int *w)
  {
!     t_clip *x = (t_clip *)(w[1]);
!     t_float *in = (t_float *)(w[2]);
!     t_float *out = (t_float *)(w[3]);
!     int n = (int)(w[4]);
      while (n--)
      {
          float f = *in++;
!         if (f < x->x_lo) f = x->x_lo;
!         if (f > x->x_hi) f = x->x_hi;
          *out++ = f;
      }
!     return (w+5);
  }
  
  static void clip_dsp(t_clip *x, t_signal **sp)
  {
!     dsp_add(clip_perform, 4, x, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
  }
  
--- 37,63 ----
  }
  
+ /* T.Grill - changed function interface so that class pointer needn't be passed */
  static t_int *clip_perform(t_int *w)
  {
!     t_float *in = (t_float *)(w[1]);
!     t_float *out = (t_float *)(w[2]);
!     const t_float lo = *(t_float *)(w[3]),hi = *(t_float *)(w[4]);
!     int n = (int)(w[5]);
      while (n--)
      {
          float f = *in++;
!     	if (f < lo) f = lo;
!     	else if (f > hi) f = hi;
          *out++ = f;
      }
!     return (w+6);
  }
  
  static void clip_dsp(t_clip *x, t_signal **sp)
  {
! 	if(SIMD_CHECK2(sp[0]->s_n,sp[0]->s_vec,sp[1]->s_vec))
!     	dsp_add(clip_perf_simd, 5, sp[0]->s_vec, sp[1]->s_vec, &x->x_lo, &x->x_hi, sp[0]->s_n);
!     else
! 	    dsp_add(clip_perform, 5, sp[0]->s_vec, sp[1]->s_vec, &x->x_lo, &x->x_hi, sp[0]->s_n);
  }
  
***************
*** 151,155 ****
  static void sigrsqrt_dsp(t_sigrsqrt *x, t_signal **sp)
  {
!     dsp_add(sigrsqrt_perform, 3, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
  }
  
--- 158,165 ----
  static void sigrsqrt_dsp(t_sigrsqrt *x, t_signal **sp)
  {
! 	if(SIMD_CHECK2(sp[0]->s_n,sp[0]->s_vec,sp[1]->s_vec))
!     	dsp_add(sigrsqrt_perf_simd, 3, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
!     else
! 		dsp_add(sigrsqrt_perform, 3, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
  }
  
***************
*** 205,209 ****
  static void sigsqrt_dsp(t_sigsqrt *x, t_signal **sp)
  {
!     dsp_add(sigsqrt_perform, 3, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
  }
  
--- 215,222 ----
  static void sigsqrt_dsp(t_sigsqrt *x, t_signal **sp)
  {
! 	if(SIMD_CHECK2(sp[0]->s_n,sp[0]->s_vec,sp[1]->s_vec))
!     	dsp_add(sigsqrt_perf_simd, 3, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
!     else
! 		dsp_add(sigsqrt_perform, 3, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
  }
  
***************
*** 251,255 ****
  static void sigwrap_dsp(t_sigwrap *x, t_signal **sp)
  {
!     dsp_add(sigwrap_perform, 3, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
  }
  
--- 264,271 ----
  static void sigwrap_dsp(t_sigwrap *x, t_signal **sp)
  {
! 	if(SIMD_CHECK2(sp[0]->s_n,sp[0]->s_vec,sp[1]->s_vec))
!     	dsp_add(sigwrap_perf_simd, 3, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
!     else
! 		dsp_add(sigwrap_perform, 3, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
  }
  

Index: d_global.c
===================================================================
RCS file: /cvsroot/pure-data/pd/src/d_global.c,v
retrieving revision 1.2
retrieving revision 1.2.4.1
diff -C2 -d -r1.2 -r1.2.4.1
*** d_global.c	6 Sep 2004 20:20:33 -0000	1.2
--- d_global.c	5 Nov 2004 13:55:58 -0000	1.2.4.1
***************
*** 6,9 ****
--- 6,10 ----
  
  #include "m_pd.h"
+ #include "m_simd.h"
  #include <string.h>
  
***************
*** 28,32 ****
      x->x_sym = s;
      x->x_n = DEFSENDVS;
!     x->x_vec = (float *)getbytes(DEFSENDVS * sizeof(float));
      memset((char *)(x->x_vec), 0, DEFSENDVS * sizeof(float));
      x->x_f = 0;
--- 29,33 ----
      x->x_sym = s;
      x->x_n = DEFSENDVS;
!     x->x_vec = (float *)getalignedbytes(DEFSENDVS * sizeof(float));
      memset((char *)(x->x_vec), 0, DEFSENDVS * sizeof(float));
      x->x_f = 0;
***************
*** 48,56 ****
  }
  
  static void sigsend_dsp(t_sigsend *x, t_signal **sp)
  {
!     if (x->x_n == sp[0]->s_n)
!         dsp_add(sigsend_perform, 3, sp[0]->s_vec, x->x_vec, sp[0]->s_n);
!     else error("sigsend %s: unexpected vector size", x->x_sym->s_name);
  }
  
--- 49,70 ----
  }
  
+ /* T.Grill - SIMD version */
+ static t_int *sigsend_perfsimd(t_int *w)
+ {
+     testcopyvec_simd((t_float *)w[2],(t_float *)w[1],w[3]);
+     return (w+4);
+ }
+ 
  static void sigsend_dsp(t_sigsend *x, t_signal **sp)
  {
!     const int n = x->x_n;
!     if(n == sp[0]->s_n) {
!         if(SIMD_CHECK1(n,sp[0]->s_vec)) /* x->x_vec is aligned in any case */
!     	    dsp_add(sigsend_perfsimd, 3, sp[0]->s_vec, x->x_vec, n);
!         else
!     	    dsp_add(sigsend_perform, 3, sp[0]->s_vec, x->x_vec, n);
!     }
!     else 
!         error("sigsend %s: unexpected vector size", x->x_sym->s_name);
  }
  
***************
*** 58,62 ****
  {
      pd_unbind(&x->x_obj.ob_pd, x->x_sym);
!     freebytes(x->x_vec, x->x_n * sizeof(float));
  }
  
--- 72,76 ----
  {
      pd_unbind(&x->x_obj.ob_pd, x->x_sym);
!     freealignedbytes(x->x_vec,x->x_n* sizeof(float));
  }
  
***************
*** 114,136 ****
  {
      t_sigreceive *x = (t_sigreceive *)(w[1]);
-     t_float *out = (t_float *)(w[2]);
-     int n = (int)(w[3]);
      t_float *in = x->x_wherefrom;
      if (in)
      {
!         for (; n; n -= 8, in += 8, out += 8)
!         {
!             out[0] = in[0]; out[1] = in[1]; out[2] = in[2]; out[3] = in[3]; 
!             out[4] = in[4]; out[5] = in[5]; out[6] = in[6]; out[7] = in[7]; 
!         }
!     }
      else
!     {
!         for (; n; n -= 8, in += 8, out += 8)
!         {
!             out[0] = 0; out[1] = 0; out[2] = 0; out[3] = 0; 
!             out[4] = 0; out[5] = 0; out[6] = 0; out[7] = 0; 
!         }
!     }
      return (w+4);
  }
--- 128,148 ----
  {
      t_sigreceive *x = (t_sigreceive *)(w[1]);
      t_float *in = x->x_wherefrom;
      if (in)
+         copyvec_8((t_float *)w[2],in,w[3]);
+     else 
+         zerovec_8((t_float *)w[2],w[3]);
+     return (w+4);
+ }
+ 
+ /* T.Grill - SIMD version */
+ static t_int *sigreceive_perfsimd(t_int *w)
      {
!     t_sigreceive *x = (t_sigreceive *)(w[1]);
!     t_float *in = x->x_wherefrom;
!     if(in) 
!         copyvec_simd((t_float *)w[2],in,w[3]);
      else
!         zerovec_simd((t_float *)w[2],w[3]);
      return (w+4);
  }
***************
*** 159,163 ****
  static void sigreceive_dsp(t_sigreceive *x, t_signal **sp)
  {
!     if (sp[0]->s_n != x->x_n)
      {
          pd_error(x, "receive~ %s: vector size mismatch", x->x_sym->s_name);
--- 171,176 ----
  static void sigreceive_dsp(t_sigreceive *x, t_signal **sp)
  {
!     const int n = x->x_n;
!     if (sp[0]->s_n != n)
      {
          pd_error(x, "receive~ %s: vector size mismatch", x->x_sym->s_name);
***************
*** 166,174 ****
      {
          sigreceive_set(x, x->x_sym);
!         if (sp[0]->s_n&7)
!             dsp_add(sigreceive_perform, 3,
!                 x, sp[0]->s_vec, sp[0]->s_n);
!         else dsp_add(sigreceive_perf8, 3,
!             x, sp[0]->s_vec, sp[0]->s_n);
      }
  }
--- 179,190 ----
      {
          sigreceive_set(x, x->x_sym);
! 	    if(n&7)
! 	        dsp_add(sigreceive_perform, 3, x, sp[0]->s_vec, n);
!         else 
! 			if(SIMD_CHECK1(n,sp[0]->s_vec))
! 				/* x->x_wherefrom is aligned because we aligned the sender memory buffer */
! 				dsp_add(sigreceive_perfsimd, 3, x, sp[0]->s_vec, n);
! 			else
! 				dsp_add(sigreceive_perf8, 3, x, sp[0]->s_vec, n);
      }
  }
***************
*** 204,208 ****
      x->x_sym = s;
      x->x_n = DEFSENDVS;
!     x->x_vec = (float *)getbytes(DEFSENDVS * sizeof(float));
      memset((char *)(x->x_vec), 0, DEFSENDVS * sizeof(float));
      outlet_new(&x->x_obj, &s_signal);
--- 220,224 ----
      x->x_sym = s;
      x->x_n = DEFSENDVS;
!     x->x_vec = (float *)getalignedbytes(DEFSENDVS * sizeof(float));
      memset((char *)(x->x_vec), 0, DEFSENDVS * sizeof(float));
      outlet_new(&x->x_obj, &s_signal);
***************
*** 222,236 ****
  static t_int *sigcatch_perf8(t_int *w)
  {
!     t_float *in = (t_float *)(w[1]);
!     t_float *out = (t_float *)(w[2]);
!     int n = (int)(w[3]);
!     for (; n; n -= 8, in += 8, out += 8)
      {
!        out[0] = in[0]; out[1] = in[1]; out[2] = in[2]; out[3] = in[3]; 
!        out[4] = in[4]; out[5] = in[5]; out[6] = in[6]; out[7] = in[7]; 
!     
!        in[0] = 0; in[1] = 0; in[2] = 0; in[3] = 0; 
!        in[4] = 0; in[5] = 0; in[6] = 0; in[7] = 0; 
!     }
      return (w+4);
  }
--- 238,251 ----
  static t_int *sigcatch_perf8(t_int *w)
  {
!     copyvec_8((t_float *)w[2],(t_float *)w[1],w[3]);
!     zerovec_8((t_float *)w[1],w[3]);
!     return (w+4);
! }
! 
! /* T.Grill: SIMD catch function */
! static t_int *sigcatch_perfsimd(t_int *w)
      {
!     copyvec_simd((t_float *)w[2],(t_float *)w[1],w[3]);
!     zerovec_simd((t_float *)w[1],w[3]);
      return (w+4);
  }
***************
*** 238,247 ****
  static void sigcatch_dsp(t_sigcatch *x, t_signal **sp)
  {
!     if (x->x_n == sp[0]->s_n)
      {
!         if(sp[0]->s_n&7)
!         dsp_add(sigcatch_perform, 3, x->x_vec, sp[0]->s_vec, sp[0]->s_n);
!         else
!         dsp_add(sigcatch_perf8, 3, x->x_vec, sp[0]->s_vec, sp[0]->s_n);
      }
      else error("sigcatch %s: unexpected vector size", x->x_sym->s_name);
--- 253,266 ----
  static void sigcatch_dsp(t_sigcatch *x, t_signal **sp)
  {
!     const int n = sp[0]->s_n;
!     if (x->x_n == n)
      {
!     	if(n&7)
!     	    dsp_add(sigcatch_perform, 3, x->x_vec, sp[0]->s_vec, n);
!     	else 
! 			if(SIMD_CHECK2(n,x->x_vec,sp[0]->s_vec))
! 				dsp_add(sigcatch_perfsimd, 3, x->x_vec, sp[0]->s_vec, n);
! 			else
! 				dsp_add(sigcatch_perf8, 3, x->x_vec, sp[0]->s_vec, n);
      }
      else error("sigcatch %s: unexpected vector size", x->x_sym->s_name);
***************
*** 251,255 ****
  {
      pd_unbind(&x->x_obj.ob_pd, x->x_sym);
!     freebytes(x->x_vec, x->x_n * sizeof(float));
  }
  
--- 270,274 ----
  {
      pd_unbind(&x->x_obj.ob_pd, x->x_sym);
!     freealignedbytes(x->x_vec,x->x_n* sizeof(float));
  }
  
***************
*** 302,305 ****
--- 321,333 ----
  }
  
+ /* T.Grill - SIMD version */
+ static t_int *sigthrow_perfsimd(t_int *w)
+ {
+     t_sigthrow *x = (t_sigthrow *)(w[1]);
+     t_float *out = x->x_whereto;
+     if(out) testaddvec_simd(out,(t_float *)w[2],w[3]);
+     return (w+4);
+ }
+ 
  static void sigthrow_set(t_sigthrow *x, t_symbol *s)
  {
***************
*** 325,329 ****
  static void sigthrow_dsp(t_sigthrow *x, t_signal **sp)
  {
!     if (sp[0]->s_n != x->x_n)
      {
          pd_error(x, "throw~ %s: vector size mismatch", x->x_sym->s_name);
--- 353,358 ----
  static void sigthrow_dsp(t_sigthrow *x, t_signal **sp)
  {
!     const int n = x->x_n;
!     if (sp[0]->s_n != n)
      {
          pd_error(x, "throw~ %s: vector size mismatch", x->x_sym->s_name);
***************
*** 332,337 ****
      {
          sigthrow_set(x, x->x_sym);
!         dsp_add(sigthrow_perform, 3,
!             x, sp[0]->s_vec, sp[0]->s_n);
      }
  }
--- 361,369 ----
      {
          sigthrow_set(x, x->x_sym);
!         if(SIMD_CHECK1(n,sp[0]->s_vec))
!             /* the memory of the catcher is aligned in any case */
!     	    dsp_add(sigthrow_perfsimd, 3, x, sp[0]->s_vec, n);
!         else
!     	    dsp_add(sigthrow_perform, 3, x, sp[0]->s_vec, n);
      }
  }

Index: d_osc.c
===================================================================
RCS file: /cvsroot/pure-data/pd/src/d_osc.c,v
retrieving revision 1.2
retrieving revision 1.2.4.1
diff -C2 -d -r1.2 -r1.2.4.1
*** d_osc.c	6 Sep 2004 20:20:33 -0000	1.2
--- d_osc.c	5 Nov 2004 13:55:58 -0000	1.2.4.1
***************
*** 19,23 ****
  #define int32 long  /* a data type that has 32 bits */
  #else
! #ifdef MSW
      /* little-endian; most significant byte is at highest address */
  #define HIOFFSET 1
--- 19,23 ----
  #define int32 long  /* a data type that has 32 bits */
  #else
! #if defined(MSW) || defined(__CYGWIN__)
      /* little-endian; most significant byte is at highest address */
  #define HIOFFSET 1
***************
*** 270,273 ****
--- 270,274 ----
      outlet_new(&x->x_obj, gensym("signal"));
      inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("ft1"));
+     inlet_settip(x->x_obj.te_inlet,gensym("phase"));
      x->x_phase = 0;
      x->x_conv = 0;
***************
*** 350,353 ****
--- 351,355 ----
      class_addmethod(osc_class, (t_method)osc_dsp, gensym("dsp"), 0);
      class_addmethod(osc_class, (t_method)osc_ft1, gensym("ft1"), A_FLOAT, 0);
+     class_settip(osc_class,gensym("frequency"));
  
      cos_maketable();





More information about the Pd-cvs mailing list