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