Commit daa16d93 authored by Miller Puckette's avatar Miller Puckette
Browse files

many bug fixes; added new pd~, stdout extras

parent 22ffb531
......@@ -20,6 +20,16 @@
<H3> <A name="s2"> 5.1. release notes </A> </H3>
<P> ------------------ 0.42 ---------------------------
<P> ".pdrc" loading suppressed if pd is started with "-noprefs".
<P> Bug fix in pipe object: if sending a list to pipe, it didn't update the
delay time when asked to.
<P> Binbufs fixed to handle arbitrary length messages. (This fixed a problem
reloading data structures with huge arrays).
<P> ------------------ 0.41-3,4 ---------------------------
<P> 2 fixes for PC: no bonk~, and the audio device selection
......
#N canvas 25 8 688 708 12;
#N canvas 247 4 688 708 12;
#X floatatom 38 264 7 0 0 0 - - -;
#N canvas 0 0 450 300 graph1 0;
#N canvas 0 0 450 300 (subpatch) 0;
#X array \$0-real 64 float 2;
#X coords 0 64 64 -64 256 200 1;
#X restore 423 184 graph;
......@@ -12,7 +12,7 @@
#X obj 38 637 tabwrite~ \$0-real;
#X obj 67 614 tabwrite~ \$0-imaginary;
#X obj 38 384 osc~;
#N canvas 0 0 450 300 graph1 0;
#N canvas 0 0 450 300 (subpatch) 0;
#X array \$0-imaginary 64 float 2;
#X coords 0 64 64 -64 256 200 1;
#X restore 423 417 graph;
......@@ -20,8 +20,8 @@
#X floatatom 91 316 3 0 100 0 - - -;
#X obj 91 337 / 100;
#X obj 38 191 / 64;
#X text 504 163 real part;
#X text 489 398 imaginary part;
#X text 595 165 real part;
#X text 550 398 imaginary part;
#X obj 80 545 loadbang;
#X text 94 166 <- frequency;
#X text 133 182 (as multiple;
......
#N canvas 35 5 531 296 10;
#X obj 19 107 sig~;
#X obj 50 167 loadbang;
#X obj 50 191 metro 100;
#X obj 50 215 snapshot~;
#X floatatom 19 88 5 0 0 0 - - -;
#X floatatom 50 240 7 0 0 0 - - -;
#X text 314 271 updated for Pd version 0.42.;
#X text 83 131 <-- optional creation argument initializes right inlet
(the base of the logarithm).;
#X obj 21 14 exp~;
#X text 60 14 - exponential function;
#X text 76 31 raises the Euler number 'e' (about 2.718) \, to the power
of the input signal.;
#X text 18 272 See also:;
#X obj 92 271 pow~;
#X obj 20 132 exp~;
#X connect 0 0 13 0;
#X connect 1 0 2 0;
#X connect 2 0 3 0;
#X connect 3 0 5 0;
#X connect 4 0 0 0;
#X connect 13 0 3 0;
......@@ -81,15 +81,15 @@
#X text 119 1178 - greater or lesser of 2 numbers;
#X obj 19 1201 clip;
#X text 119 1201 - force a number into a range;
#X obj 16 1251 notein;
#X obj 75 1251 ctlin;
#X obj 126 1251 pgmin;
#X obj 176 1251 bendin;
#X obj 235 1251 touchin;
#X obj 16 1274 polytouchin;
#X obj 120 1274 midiin;
#X obj 179 1274 sysexin;
#X text 318 1263 - MIDI input;
#X obj 16 1261 notein;
#X obj 75 1261 ctlin;
#X obj 126 1261 pgmin;
#X obj 176 1261 bendin;
#X obj 235 1261 touchin;
#X obj 16 1284 polytouchin;
#X obj 120 1284 midiin;
#X obj 179 1284 sysexin;
#X text 318 1273 - MIDI input;
#X obj 19 1317 noteout;
#X obj 87 1317 ctlout;
#X obj 147 1317 pgmout;
......@@ -99,8 +99,6 @@
#X obj 210 1338 midiout;
#X text 318 1327 - MIDI output;
#X obj 20 1370 makenote;
#X text 109 1368 - schedule a delayed "note off" message corresponding
to a note-on;
#X obj 19 1402 stripnote;
#X text 112 1403 - strip "note off" messages;
#X obj 17 1441 tabread;
......@@ -143,18 +141,17 @@ to a note-on;
#X obj 16 2052 q8_rsqrt~;
#X text 116 2052 - cheap reciprocal square root (beware -- 8 bits!)
;
#X obj 16 2082 q8_sqrt~;
#X text 116 2082 - cheap square root (beware -- 8 bits!);
#X obj 16 2112 wrap~;
#X text 116 2112 - wraparound (fractional part;
#X obj 16 2142 fft~;
#X text 116 2142 - complex forward discrete Fourier transform;
#X obj 16 2172 ifft~;
#X text 116 2172 - complex inverse discrete Fourier transform;
#X obj 16 2202 rfft~;
#X text 116 2202 - real forward discrete Fourier transform;
#X obj 16 2232 rifft~;
#X text 116 2232 - real inverse discrete Fourier transform;
#X obj 16 2074 q8_sqrt~;
#X text 116 2074 - cheap square root (beware -- 8 bits!);
#X obj 16 2104 wrap~;
#X obj 16 2134 fft~;
#X text 116 2134 - complex forward discrete Fourier transform;
#X obj 16 2156 ifft~;
#X text 116 2156 - complex inverse discrete Fourier transform;
#X obj 16 2186 rfft~;
#X text 116 2186 - real forward discrete Fourier transform;
#X obj 16 2208 rifft~;
#X text 116 2208 - real inverse discrete Fourier transform;
#X obj 16 2262 framp~;
#X text 116 2262 - output a ramp for each block;
#X obj 16 2292 mtof~;
......@@ -314,7 +311,7 @@ to a note-on;
#X text 20 961 ------------------------- MATH -----------------;
#X text 19 721 ------------------------- TIME --------------------------
;
#X text 17 1232 ------------------------ MIDI -------------------------
#X text 17 1242 ------------------------ MIDI -------------------------
;
#X text 24 120 --------------- GLUE ----------------;
#X text 18 3768 ------------------------ SUBWINDOWS ------------------------
......@@ -358,3 +355,13 @@ aren't typed into object boxes but come straight off the "add" menu.)
Right-click (or double-click on a Macintosh) on any object to get its
"help window".;
#X text 118 4368 - get a pointer into a list within a scalar;
#X obj 19 1224 wrap;
#X text 118 1224 - wrap a number to range [0 \, 1);
#X text 116 2104 - wraparound (fractional part);
#X obj 15 2236 pow~;
#X obj 59 2236 log~;
#X obj 103 2236 exp~;
#X text 197 2238 - math;
#X obj 149 2237 abs~;
#X text 109 1368 - schedule delayed "note off" message corresponding
to a note-on;
#N canvas 299 273 531 296 10;
#X obj 19 103 sig~;
#X obj 50 167 loadbang;
#X obj 50 191 metro 100;
#X obj 50 215 snapshot~;
#X floatatom 19 79 5 0 0 0 - - -;
#X obj 60 103 sig~;
#X floatatom 60 79 5 0 0 0 - - -;
#X floatatom 50 240 7 0 0 0 - - -;
#X text 316 257 updated for Pd version 0.42.;
#X obj 21 14 log~;
#X text 60 14 - logarithms;
#X text 76 31 computes the logarithm of the left inlet \, to the base
'e' (about 2.718) \, or to another base specified by the inlet or a
cration argument.;
#X obj 20 132 log~ 2;
#X text 83 131 <-- optional creation argument initializes right inlet
(the base of the logarithm).;
#X connect 0 0 12 0;
#X connect 1 0 2 0;
#X connect 2 0 3 0;
#X connect 3 0 7 0;
#X connect 4 0 0 0;
#X connect 5 0 12 1;
#X connect 6 0 5 0;
#X connect 12 0 3 0;
#N canvas 191 0 534 413 10;
#X obj 21 14 pow~;
#X obj 67 109 sig~;
#X obj 98 173 loadbang;
#X obj 98 197 metro 100;
#X obj 98 221 snapshot~;
#X floatatom 67 73 5 0 0 0 - - -;
#X obj 108 109 sig~;
#X floatatom 108 73 5 0 0 0 - - -;
#X obj 68 138 pow~ 2;
#X floatatom 98 246 7 0 0 0 - - -;
#X obj 413 268 pow~ 2;
#X text 20 271 An optional creation argument initializes right inlet:
;
#X text 319 384 updated for Pd version 0.42.;
#X text 23 303 WARNING: it's easy to generate "infinity" by accident
\, and if you do \, the DSP chain may dramatically slow down if you're
using an i386 or ia64 processor. Out-of-range floating point values
are thousands of times slower to compute with than in-range ones.;
#X text 68 12 - raise a signal to a numeric power (given by another
signal). The left inlet must be a positive number. The right inlet
my be positive \, zero \, or negative.;
#X connect 1 0 8 0;
#X connect 2 0 3 0;
#X connect 3 0 4 0;
#X connect 4 0 9 0;
#X connect 5 0 1 0;
#X connect 6 0 8 1;
#X connect 7 0 6 0;
#X connect 8 0 4 0;
......@@ -23,36 +23,6 @@ PDNTLIB = /NODEFAULTLIB:libcmt /NODEFAULTLIB:oldnames /NODEFAULTLIB:kernel32 \
cl $(PDNTCFLAGS) $(PDNTINCLUDE) /c $*.c
link /nologo /dll /export:$(CSYM)_setup $*.obj $(PDNTLIB)
# ----------------------- IRIX 5.x -----------------------
pd_irix5: $(NAME).pd_irix5
.SUFFIXES: .pd_irix5
SGICFLAGS5 = -o32 -DPD -DUNIX -DIRIX -O2
SGIINCLUDE = -I../../src
.c.pd_irix5:
$(CC) $(SGICFLAGS5) $(SGIINCLUDE) -o $*.o -c $*.c
ld -elf -shared -rdata_shared -o $*.pd_irix5 $*.o
rm $*.o
# ----------------------- IRIX 6.x -----------------------
pd_irix6: $(NAME).pd_irix6
.SUFFIXES: .pd_irix6
SGICFLAGS6 = -n32 -DPD -DUNIX -DIRIX -DN32 -woff 1080,1064,1185 \
-OPT:roundoff=3 -OPT:IEEE_arithmetic=3 -OPT:cray_ivdep=true \
-Ofast=ip32
.c.pd_irix6:
$(CC) $(SGICFLAGS6) $(SGIINCLUDE) -o $*.o -c $*.c
ld -n32 -IPA -shared -rdata_shared -o $*.pd_irix6 $*.o
rm $*.o
# ----------------------- LINUX i386 -----------------------
pd_linux: $(NAME).pd_linux
......
NAME=pd~
CSYM=pd_tilde
include ../makefile
pd_linux: pdsched.pd_linux
pdsched.pd_linux: pdsched.c
$(CC) $(LINUXCFLAGS) $(LINUXINCLUDE) -o $*.o -c $*.c
$(CC) -export_dynamic -shared -o $*.pd_linux $*.o -lc -lm
strip --strip-unneeded $*.pd_linux
rm -f $*.o
pd -schedlib `pwd`/pdsched
problems:
confusion about file extent (l_ia64 / pd_linux)
Pd dies silently if scheduler doesn't load
figure out about setting nchannels from command line
maximum nchannels in and out
paper?
cost per watt
flops per watt
cost per flop
cost of multiprocessing
history - 6-processor ISPW / 1-processor PC / 4-processor PC
will multiprocessing ever get cheap enough to be worth it?
(including programming/complexity cost)
will multiprocessing be 2-to-4 or 16-up?
Max/FTS, pd, pd~
/* Copyright 2008 Miller Puckette. Berkeley license; see the
file LICENSE.txt in this distribution. */
/* A plug-in scheduler that turns Pd into a filter that inputs and
outputs audio and messages. */
/* todo:
fix schedlib code to use extent2
figure out about if (sys_externalschedlib) { return; } in s_audio.c
make buffer size ynamically growable
*/
#include "m_pd.h"
#include "s_stuff.h"
#include <stdio.h>
#define BUFSIZE 65536
static char inbuf[BUFSIZE];
int pd_extern_sched(char *flags)
{
int naudioindev, audioindev[MAXAUDIOINDEV], chindev[MAXAUDIOINDEV];
int naudiooutdev, audiooutdev[MAXAUDIOOUTDEV], choutdev[MAXAUDIOOUTDEV];
int i, j, rate, advance, callback, chin, chout, fill = 0, c;
t_binbuf *b = binbuf_new();
sys_get_audio_params(&naudioindev, audioindev, chindev,
&naudiooutdev, audiooutdev, choutdev, &rate, &advance, &callback);
chin = (naudioindev < 1 ? 0 : chindev[0]);
chout = (naudiooutdev < 1 ? 0 : choutdev[0]);
fprintf(stderr, "Pd plug-in scheduler called, chans %d %d, sr %d\n",
chin, chout, (int)rate);
sys_setchsr(chin, chout, rate);
while ((c = getchar()) != EOF)
{
if (c == ';')
{
int n;
t_atom *ap;
binbuf_text(b, inbuf, fill);
n = binbuf_getnatom(b);
ap = binbuf_getvec(b);
fill = 0;
if (n > 0 && ap[0].a_type == A_FLOAT)
{
/* a list -- take it as incoming signals. */
int chan, nchan = n/DEFDACBLKSIZE;
t_sample *fp;
for (i = chan = 0, fp = sys_soundin; chan < nchan; chan++)
for (j = 0; j < DEFDACBLKSIZE; j++)
*fp++ = atom_getfloat(ap++);
for (; chan < chin; chan++)
for (j = 0; j < DEFDACBLKSIZE; j++)
*fp++ = 0;
sched_tick(sys_time+sys_time_per_dsp_tick);
sys_pollgui();
printf(";\n");
for (i = chout*DEFDACBLKSIZE, fp = sys_soundout; i--; fp++)
{
printf("%g\n", *fp);
*fp = 0;
}
printf(";\n");
}
else if (n > 1 && ap[0].a_type == A_SYMBOL)
{
t_pd *whom = ap[0].a_w.w_symbol->s_thing;
if (!whom)
error("%s: no such object", ap[0].a_w.w_symbol->s_name);
else if (ap[1].a_type == A_SYMBOL)
typedmess(whom, ap[1].a_w.w_symbol, n-2, ap+2);
else pd_list(whom, 0, n-1, ap+1);
}
}
else if (fill < BUFSIZE)
inbuf[fill++] = c;
else if (fill == BUFSIZE)
fprintf(stderr, "pd-extern: input buffer overflow\n");
}
return (0);
}
#N canvas 315 103 450 300 10;
#X msg 52 86 foo bar baz;
#X obj 209 52 osc~ 440;
#X obj 74 211 env~ 8192;
#X floatatom 77 243 5 0 0 0 - - -;
#X obj 285 204 r a;
#X obj 281 232 print a;
#X obj 70 166 pd~ -pddir /home/msp/pd z.pd;
#X connect 0 0 6 0;
#X connect 1 0 6 0;
#X connect 2 0 3 0;
#X connect 4 0 5 0;
#X connect 6 0 2 0;
/*
pd~.c - embed a Pd process within Pd or Max.
Copyright 2008 Miller Puckette
BSD license; see README.txt in this distribution for details.
*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#ifdef NT
#pragma warning (disable: 4305 4244)
#endif
#ifdef MSP
#include "ext.h"
#include "z_dsp.h"
#include "math.h"
#include "ext_support.h"
#include "ext_proto.h"
#include "ext_obex.h"
typedef double t_floatarg;
void *pd_tilde_class;
#define getbytes t_getbytes
#define freebytes t_freebytes
#endif /* MSP */
#ifdef PD
#include "m_pd.h"
#include "s_stuff.h"
static t_class *pd_tilde_class;
char *class_gethelpdir(t_class *c);
#endif
#ifdef __linux__
#ifdef __x86_64__
static char pd_tilde_dllextent[] = ".l_ia64",
pd_tilde_dllextent2[] = ".pd_linux";
#else
static char pd_tilde_dllextent[] = ".l_i386",
pd_tilde_dllextent2[] = ".pd_linux";
#endif
#endif
#ifdef __APPLE__
static char pd_tilde_dllextent[] = ".d_ppc",
pd_tilde_dllextent2[] = ".pd_darwin";
#endif
/* ------------------------ pd_tilde~ ----------------------------- */
#define MSGBUFSIZE 65536
typedef struct _pd_tilde
{
#ifdef PD
t_object x_obj;
t_clock *x_clock;
#endif /* PD */
#ifdef MSP
t_pxobject x_obj;
void *obex;
void *x_cookedout;
void *x_clock;
short x_vol;
#endif /* MSP */
FILE *x_infd;
FILE *x_outfd;
char *x_msgbuf;
int x_msgbufsize;
int x_infill;
int x_childpid;
int x_ninsig;
int x_noutsig;
t_sample **x_insig;
t_sample **x_outsig;
} t_pd_tilde;
#ifdef MSP
static void *pd_tilde_new(t_symbol *s, long ac, t_atom *av);
static void pd_tilde_tick(t_pd_tilde *x);
static t_int *pd_tilde_perform(t_int *w);
static void pd_tilde_dsp(t_pd_tilde *x, t_signal **sp);
void pd_tilde_assist(t_pd_tilde *x, void *b, long m, long a, char *s);
static void pd_tilde_free(t_pd_tilde *x);
void pd_tilde_setup(void);
void main();
static void pd_tilde_thresh(t_pd_tilde *x, t_floatarg f1, t_floatarg f2);
void pd_tilde_minvel_set(t_pd_tilde *x, void *attr, long ac, t_atom *av);
char *strcpy(char *s1, const char *s2);
#endif
static void pd_tilde_tick(t_pd_tilde *x);
static void pd_tilde_close(t_pd_tilde *x)
{
if (x->x_outfd)
fclose(x->x_outfd);
if (x->x_infd)
fclose(x->x_infd);
if (x->x_childpid > 0)
waitpid(x->x_childpid, 0, 0);
if (x->x_msgbuf)
free(x->x_msgbuf);
x->x_infd = x->x_outfd = 0;
x->x_childpid = -1;
x->x_msgbuf = 0;
x->x_msgbufsize = 0;
}
static void pd_tilde_readmessages(t_pd_tilde *x)
{
int gotsomething = 0, setclock = 0, wasempty = (x->x_infill == 0);
FILE *infd = x->x_infd;
while (1)
{
int c = getc(infd);
if (c == EOF)
{
pd_error(x, "pd~: %s", strerror(errno));
pd_tilde_close(x);
break;
}
if (x->x_infill >= x->x_msgbufsize)
{
char *z = realloc(x->x_msgbuf, x->x_msgbufsize+MSGBUFSIZE);
if (!z)
{
pd_error(x, "pd~: failed to grow input buffer");
pd_tilde_close(x);
break;
}
x->x_msgbuf = z;
x->x_msgbufsize += MSGBUFSIZE;
}
x->x_msgbuf[x->x_infill++] = c;
if (c == ';')
{
if (!gotsomething)
break;
gotsomething = 0;
}
else if (!isspace(c))
gotsomething = setclock = 1;
}
if (setclock)
clock_delay(x->x_clock, 0);
else if (wasempty)
x->x_infill = 0;
}
static void pd_tilde_donew(t_pd_tilde *x, char *pddir, char *schedlibdir,
char *pdargs, int ninsig, int noutsig, int fifo, float samplerate)
{
int i, pid, pipe1[2], pipe2[2];
char cmdbuf[MAXPDSTRING], pdexecbuf[MAXPDSTRING], schedbuf[MAXPDSTRING];
float *fp;
t_sample **g;
struct stat statbuf;
x->x_infd = x->x_outfd = 0;
x->x_childpid = -1;
snprintf(pdexecbuf, MAXPDSTRING, "%s/bin/pd", pddir);
if (stat(pdexecbuf, &statbuf) < 0)
{
pd_error(x, "pd~: can't stat %s", pdexecbuf);
goto fail1;
}
snprintf(schedbuf, MAXPDSTRING, "%s/pdsched%s", schedlibdir,
pd_tilde_dllextent);
if (stat(schedbuf, &statbuf) < 0)
{
snprintf(schedbuf, MAXPDSTRING, "%s/pdsched%s", schedlibdir,
pd_tilde_dllextent2);
if (stat(schedbuf, &statbuf) < 0)
{
pd_error(x, "pd~: can't stat %s", schedbuf);
goto fail1;
}
}
snprintf(cmdbuf, MAXPDSTRING, "%s -schedlib %s/pdsched %s\n",
pdexecbuf, schedlibdir, pdargs);
fprintf(stderr, "%s", cmdbuf);
if (pipe(pipe1) < 0)
{
pd_error(x, "pd~: can't create pipe");
goto fail1;
}
if (pipe(pipe2) < 0)
{
pd_error(x, "pd~: can't create pipe");
goto fail2;
}
if ((pid = fork()) < 0)
{
pd_error(x, "pd~: can't fork");
goto fail3;
}
else if (pid == 0)
{
/* child process */
if (pipe2[1] == 0)
{
dup2(pipe2[1], 20);
close(pipe2[1]);
pipe2[1] = 20;
}
dup2(pipe1[0], 0);
dup2(pipe2[1], 1);
if (pipe1[0] >= 2)
close(pipe1[0]);
if (pipe1[1] >= 2)
close(pipe1[1]);
if (pipe2[0] >= 2)
close(pipe2[0]);
if (pipe2[1] >= 2)
close(pipe2[1]);
execl("/bin/sh", "sh", "-c", cmdbuf, (char*)0);
_exit(1);
}
/* OK, we're parent */
close(pipe1[0]);
close(pipe2[1]);
x->x_outfd = fdopen(pipe1[1], "w");
x->x_infd = fdopen(pipe2[0], "r");
x->x_childpid = pid;
for (i = 0; i < fifo; i++)
fprintf(x->x_outfd, "%s", ";\n0;\n");
fflush(x->x_outfd);
if (!(x->x_msgbuf = calloc(MSGBUFSIZE, 1)))
{
pd_error(x, "pd~: can't allocate message buffer");
goto fail3;
}