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();