aboutsummaryrefslogtreecommitdiff
path: root/signal
diff options
context:
space:
mode:
Diffstat (limited to 'signal')
-rwxr-xr-xsignal/Makefile51
-rw-r--r--signal/apply~.c151
-rw-r--r--signal/apply~.pd19
-rwxr-xr-xsignal/atan2~.c86
-rwxr-xr-xsignal/atan2~.pd4
-rwxr-xr-xsignal/mixer~.c107
-rwxr-xr-xsignal/mixer~.pd87
-rwxr-xr-xsignal/pipewrite~.c216
-rwxr-xr-xsignal/rtin~.c76
-rwxr-xr-xsignal/rtin~.pd32
-rwxr-xr-xsignal/sfread~.c317
-rwxr-xr-xsignal/sfread~.pd44
-rwxr-xr-xsignal/sfwrite.pd45
-rwxr-xr-xsignal/sfwrite~.c284
-rwxr-xr-xsignal/stream.h30
-rwxr-xr-xsignal/streamin~.c404
-rwxr-xr-xsignal/streamin~.pd41
-rwxr-xr-xsignal/streamout~.c323
-rwxr-xr-xsignal/streamout~.pd49
19 files changed, 2366 insertions, 0 deletions
diff --git a/signal/Makefile b/signal/Makefile
new file mode 100755
index 0000000..ebf4c30
--- /dev/null
+++ b/signal/Makefile
@@ -0,0 +1,51 @@
+current: nt
+
+
+# TARGETS += stk
+
+VERSION = \"0.16\"
+
+.SUFFIXES: .dll .obj
+# ----------------------- NT ----------------------------
+
+NTOBJECTS = *.obj
+NTDLLS = *.dll
+
+PDNTCFLAGS = /W3 /WX /DNT /DPD /nologo
+
+PDNTINCLUDE = /I. /I..\..\pd\src /I..\include
+ProgramFiles = C:\Program Files
+PDNTLDIR = "$(ProgramFiles)\Microsoft Visual Studio\Vc98\lib"
+#PDNTLDIR = "C:\Programme\Msdev\Vc98\lib"
+
+PDNTLIB = $(PDNTLDIR)\libc.lib \
+ $(PDNTLDIR)\oldnames.lib \
+ $(PDNTLDIR)\wsock32.lib \
+ $(PDNTLDIR)\kernel32.lib \
+ $(PDNTLDIR)\uuid.lib \
+ ..\..\pd\bin\pd.lib
+
+nt: $(NTOBJECTS)
+ -link /dll $(PDNTLIB) sfplay~.obj /export:sfplay_tilde_setup
+ -link /dll $(PDNTLIB) atan2~.obj /export:atan2_tilde_setup
+ -link /dll $(PDNTLIB) exp~.obj /export:exp_tilde_setup
+ -link /dll $(PDNTLIB) log~.obj /export:log_tilde_setup
+ -link /dll $(PDNTLIB) mixer~.obj /export:mixer_tilde_setup
+ -link /dll $(PDNTLIB) sfwrite~.obj /export:swrite_tilde_setup
+ -link /dll $(PDNTLIB) streamin~.obj /export:streamin_tilde_setup
+ -link /dll $(PDNTLIB) streamout~.obj /export:streamout_tilde_setup
+ -link /dll $(PDNTLIB) moog~.obj /export:moog_tilde_setup
+
+clean:
+ del *.obj
+ del *.dll
+
+
+.c.obj:
+ -cl $(PDNTCFLAGS) $(PDNTINCLUDE) /c $*.c
+
+.obj.dll:
+
+
+
+
diff --git a/signal/apply~.c b/signal/apply~.c
new file mode 100644
index 0000000..7463383
--- /dev/null
+++ b/signal/apply~.c
@@ -0,0 +1,151 @@
+/* (C) Guenter Geiger <geiger@epy.co.at> */
+
+
+#include "math.h"
+#include <m_pd.h>
+
+/* ----------------------------- apply ----------------------------- */
+static t_class *apply_class;
+
+
+typedef double (*t_apply_onearg)(double);
+typedef double (*t_apply_twoarg)(double);
+
+static double nop(double f) {
+ return f;
+}
+
+typedef struct _funlist {
+ char* name;
+ t_int* fun;
+ int numarg;
+ char* desc;
+} t_funlist;
+
+#define MFUN1(x,d) {#x,(t_int*)x,1,d}
+
+static t_funlist funlist[] =
+ {
+ MFUN1(nop,"does nothing"),
+ MFUN1(sin,"calculate sine"),
+ MFUN1(asin,"calculate arcus sine"),
+ MFUN1(cos,"calculate cosine"),
+ MFUN1(acos,"calculate arcus cosine"),
+ MFUN1(tan,"calculate tangent"),
+ MFUN1(atan,"calculate arcus tangent"),
+
+ MFUN1(sinh,""),
+ MFUN1(asinh,""),
+ MFUN1(cosh,""),
+ MFUN1(acosh,""),
+ MFUN1(tanh,""),
+ MFUN1(atanh,""),
+
+ MFUN1(exp,""),
+ MFUN1(expm1,""),
+ // MFUN1(exp10),
+ // MFUN1(pow10),
+ MFUN1(log,""),
+ MFUN1(log1p,""),
+ MFUN1(log10,""),
+ // MFUN1(log2),
+ MFUN1(sqrt,""),
+ MFUN1(cbrt,""),
+
+
+ MFUN1(rint,""),
+ // MFUN1(round),
+ MFUN1(ceil,""),
+ MFUN1(floor,""),
+ // MFUN1(trunc),
+
+ MFUN1(erf,""),
+ MFUN1(erfc,""),
+ MFUN1(gamma,""),
+ MFUN1(lgamma,""),
+ // MFUN1(tgamma),
+
+ MFUN1(j0,""),
+ MFUN1(j1,""),
+ MFUN1(y0,""),
+ MFUN1(j1,"")
+ };
+
+
+
+typedef struct _apply
+{
+ t_object x_obj;
+ t_int* x_fun;
+} t_apply;
+
+static void *apply_new(t_symbol *s, int argc, t_atom *argv)
+{
+ t_symbol* fname;
+ int i;
+ int numfun = sizeof(funlist)/sizeof(t_funlist);
+ t_apply *x = (t_apply *)pd_new(apply_class);
+ outlet_new(&x->x_obj, &s_signal);
+
+ x->x_fun = (t_int*)nop;
+ if (argc < 1) {
+ post("nop operation requested");
+ }
+ else {
+ if (argv[0].a_type != A_SYMBOL)
+ goto nofun;
+ fname = atom_getsymbol(argv);
+ for (i=0;i<numfun;i++)
+ if (!strcmp(fname->s_name,funlist[i].name))
+ x->x_fun = funlist[i].fun;
+
+
+
+ }
+
+
+ return (x);
+ nofun:
+ post("apply first argument has to be a function");
+ return (x);
+}
+
+
+static void apply_what(t_apply* x)
+{
+ int i;
+ int numfun = sizeof(funlist)/sizeof(t_funlist);
+ for (i=0;i<numfun;i++)
+ post("function: %s: %s",funlist[i].name,funlist[i].desc);
+}
+
+t_int *apply_perform(t_int *w)
+{
+ t_apply* x = (t_apply*)(w[1]);
+ t_float *in1 = (t_float *)(w[2]);
+ t_float *out = (t_float *)(w[3]);
+
+ int n = (int)(w[4]);
+ while (n--) *out++ = (t_float) ((t_apply_onearg)x->x_fun)(*in1++);
+ return (w+5);
+}
+
+
+void dsp_add_apply(t_apply* x,t_sample *in1, t_sample *out, int n)
+{
+ dsp_add(apply_perform, 4,x, in1, out, n);
+}
+
+static void apply_dsp(t_apply *x, t_signal **sp)
+{
+ dsp_add_apply(x,sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
+}
+
+void apply_tilde_setup(void)
+{
+ apply_class = class_new(gensym("apply~"), (t_newmethod)apply_new, 0,
+ sizeof(t_apply), 0, A_GIMME, 0);
+ class_addmethod(apply_class, nullfn, gensym("signal"), 0);
+ class_addmethod(apply_class, (t_method)apply_dsp, gensym("dsp"), 0);
+ class_addmethod(apply_class, (t_method)apply_what, gensym("what"), 0);
+}
diff --git a/signal/apply~.pd b/signal/apply~.pd
new file mode 100644
index 0000000..b348a94
--- /dev/null
+++ b/signal/apply~.pd
@@ -0,0 +1,19 @@
+#N canvas 284 112 450 300 10;
+#X obj 33 88 sig~;
+#X obj 33 160 snapshot~;
+#X floatatom 33 183 10 0 0;
+#X msg 70 89 bang;
+#X floatatom 33 42 5 0 0;
+#X obj 148 112 apply~;
+#X msg 148 48 what;
+#X obj 33 118 apply~ rint;
+#X obj 295 41 loadbang;
+#X msg 295 63 \; pd dsp 1;
+#X connect 0 0 7 0;
+#X connect 1 0 2 0;
+#X connect 3 0 1 0;
+#X connect 4 0 0 0;
+#X connect 4 0 3 0;
+#X connect 6 0 5 0;
+#X connect 7 0 1 0;
+#X connect 8 0 9 0;
diff --git a/signal/atan2~.c b/signal/atan2~.c
new file mode 100755
index 0000000..0e1deb0
--- /dev/null
+++ b/signal/atan2~.c
@@ -0,0 +1,86 @@
+/* (C) Guenter Geiger <geiger@epy.co.at> */
+
+
+
+#include "math.h"
+#include <m_pd.h>
+
+/* ----------------------------- atan2 ----------------------------- */
+static t_class *atan2_class;
+
+
+#define INVTWOPI 0.15915494f
+
+typedef struct _atan2
+{
+ t_object x_obj;
+} t_atan2;
+
+static void *atan2_new(t_symbol *s, int argc, t_atom *argv)
+{
+ if (argc > 1) post("+~: extra arguments ignored");
+ {
+ t_atan2 *x = (t_atan2 *)pd_new(atan2_class);
+ inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal);
+ outlet_new(&x->x_obj, &s_signal);
+ return (x);
+ }
+}
+
+t_int *atan2_perform(t_int *w)
+{
+ t_float *in1 = (t_float *)(w[1]);
+ t_float *in2 = (t_float *)(w[2]);
+ t_float *out = (t_float *)(w[3]);
+
+ int n = (int)(w[4]);
+ while (n--) *out++ = (t_float) atan2(*in1++,*in2++) *INVTWOPI;
+ return (w+5);
+}
+
+t_int *atan2_perf8(t_int *w)
+{
+ t_float *in1 = (t_float *)(w[1]);
+ t_float *in2 = (t_float *)(w[2]);
+ t_float *out = (t_float *)(w[3]);
+ int n = (int)(w[4]);
+ for (; n; n -= 8, in1 += 8, in2 += 8, out += 8)
+ {
+ float f0 = in1[0], f1 = in1[1], f2 = in1[2], f3 = in1[3];
+ float f4 = in1[4], f5 = in1[5], f6 = in1[6], f7 = in1[7];
+
+ float g0 = in2[0], g1 = in2[1], g2 = in2[2], g3 = in2[3];
+ float g4 = in2[4], g5 = in2[5], g6 = in2[6], g7 = in2[7];
+
+ out[0] = (t_float) atan2(f0,g0)*INVTWOPI;
+ out[1] = (t_float) atan2(f1,g1)*INVTWOPI;
+ out[2] = (t_float) atan2(f2,g2)*INVTWOPI;
+ out[3] = (t_float) atan2(f3,g3)*INVTWOPI;
+ out[4] = (t_float) atan2(f4,g4)*INVTWOPI;
+ out[5] = (t_float) atan2(f5,g5)*INVTWOPI;
+ out[6] = (t_float) atan2(f6,g6)*INVTWOPI;
+ out[7] = (t_float) atan2(f7,g7)*INVTWOPI;
+ }
+ return (w+5);
+}
+
+void dsp_add_atan2(t_sample *in1, t_sample *in2, t_sample *out, int n)
+{
+ if (n&7)
+ dsp_add(atan2_perform, 4, in1, in2, out, n);
+ else
+ dsp_add(atan2_perf8, 4, in1, in2, out, n);
+}
+
+static void atan2_dsp(t_atan2 *x, t_signal **sp)
+{
+ dsp_add_atan2(sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[0]->s_n);
+}
+
+void atan2_tilde_setup(void)
+{
+ atan2_class = class_new(gensym("atan2~"), (t_newmethod)atan2_new, 0,
+ sizeof(t_atan2), 0, A_GIMME, 0);
+ class_addmethod(atan2_class, nullfn, gensym("signal"), 0);
+ class_addmethod(atan2_class, (t_method)atan2_dsp, gensym("dsp"), 0);
+}
diff --git a/signal/atan2~.pd b/signal/atan2~.pd
new file mode 100755
index 0000000..e7ff494
--- /dev/null
+++ b/signal/atan2~.pd
@@ -0,0 +1,4 @@
+#N canvas 197 203 500 184 10;
+#X obj 33 88 atan2~;
+#X text 30 121 (C) Guenter Geiger;
+#X text 30 18 The atan2 function is used to get the phase from a imaginary value of the fft.;
diff --git a/signal/mixer~.c b/signal/mixer~.c
new file mode 100755
index 0000000..5d90285
--- /dev/null
+++ b/signal/mixer~.c
@@ -0,0 +1,107 @@
+/* (C) Oswald Berthold <opt@web.fm> */
+
+
+#include "math.h"
+#include <m_pd.h>
+
+/* ----------------------------- mixer ----------------------------- */
+static t_class *mixer_class;
+
+
+
+typedef struct _mixer
+{
+ t_object x_obj;
+ t_int x_n;
+ t_float* x_m;
+} t_mixer;
+
+static void *mixer_new(t_symbol *s, t_floatarg num)
+{
+ int i;
+ t_mixer *x = (t_mixer *)pd_new(mixer_class);
+ if (num < 1) x->x_n = 1;
+ else x->x_n = (int) num;
+
+ x->x_m = getbytes(sizeof(t_float)*x->x_n);
+
+ for (i=0;i<x->x_n /* - 1 */ ;i++) {
+ inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal);
+ x->x_m[i] = 1.;
+ }
+
+
+
+ outlet_new(&x->x_obj, &s_signal);
+ return (x);
+}
+
+void mixer_list(t_mixer* x,t_symbol* s,t_int argc, t_atom* argv)
+{
+ int chan;
+ t_float val;
+
+ if (argc != 2) {
+ post("unknown");
+ return;
+ }
+
+ chan = (int) atom_getfloat(argv++);
+ val = atom_getfloat(argv++);
+
+
+ x->x_m[chan] = val;
+
+}
+
+
+t_int *mixer_perform(t_int *w)
+{
+ t_mixer* x = (t_mixer*) (w[1]);
+ int n = (int)(w[2]);
+ t_float **in = getbytes(sizeof(float)*x->x_n);
+ t_float *out;
+ int i,j;
+ int offset = 3;
+
+ for (i=0;i < x->x_n;i++) {
+ in[i] = (t_float *)(w[offset+i]);
+ }
+
+ out = (t_float *)(w[offset+i]);
+
+ while (n--) {
+ *out = 0.;
+ for (j=0;j<x->x_n;j++) {
+ *out += *(in[j]++) * x->x_m[j];
+ }
+ out++;
+ }
+ return (w+offset+1+i);
+}
+
+static void mixer_dsp(t_mixer *x, t_signal **sp)
+{
+ int i;
+ t_int** myvec = getbytes(sizeof(t_int)*(x->x_n + 3));
+
+ myvec[0] = (t_int*)x;
+ myvec[1] = (t_int*)sp[0]->s_n;
+
+ for (i=0;i < x->x_n+1;i++)
+ myvec[2 + i] = (t_int*)sp[i]->s_vec;
+
+ dsp_addv(mixer_perform, x->x_n + 3, (t_int*)myvec);
+ freebytes(myvec,sizeof(t_int)*(x->x_n + 3));
+}
+
+void mixer_tilde_setup(void)
+{
+ mixer_class = class_new(gensym("mixer~"), (t_newmethod)mixer_new, 0,
+ sizeof(t_mixer), 0, A_DEFFLOAT, A_DEFSYM,A_NULL);
+ class_addmethod(mixer_class, nullfn, gensym("signal"), 0);
+ class_addmethod(mixer_class, (t_method)mixer_dsp, gensym("dsp"), 0);
+
+ class_addlist(mixer_class,mixer_list);
+}
+
diff --git a/signal/mixer~.pd b/signal/mixer~.pd
new file mode 100755
index 0000000..1063de1
--- /dev/null
+++ b/signal/mixer~.pd
@@ -0,0 +1,87 @@
+#N canvas 205 153 590 395 10;
+#X obj 163 120 osc~ 220;
+#X obj 186 297 dac~;
+#X obj 163 140 *~ 0.1;
+#X obj 217 120 osc~ 220;
+#X obj 217 140 *~ 0.1;
+#X obj 272 120 osc~ 220;
+#X obj 272 140 *~ 0.1;
+#X obj 325 120 osc~ 220;
+#X obj 325 140 *~ 0.1;
+#X floatatom 217 97 0 0 0;
+#X floatatom 273 98 0 0 0;
+#X floatatom 326 95 0 0 0;
+#X floatatom 166 96 0 0 0;
+#X msg 106 175 1 \$1;
+#X msg 104 198 2 \$1;
+#X msg 104 221 3 \$1;
+#X floatatom 58 114 0 0 0;
+#X floatatom 58 153 0 0 0;
+#X floatatom 59 201 0 0 0;
+#X floatatom 59 84 0 0 0;
+#X msg 105 143 0 \$1;
+#X obj 196 246 mixer~ 20 --------------------------------------;
+#X obj 386 119 osc~ 220;
+#X obj 386 139 *~ 0.1;
+#X obj 440 119 osc~ 220;
+#X obj 440 139 *~ 0.1;
+#X obj 495 119 osc~ 220;
+#X obj 495 139 *~ 0.1;
+#X obj 548 119 osc~ 220;
+#X obj 548 139 *~ 0.1;
+#X floatatom 440 96 0 0 0;
+#X floatatom 496 97 0 0 0;
+#X floatatom 549 94 0 0 0;
+#X floatatom 389 95 0 0 0;
+#X floatatom 55 251 0 0 0;
+#X floatatom 55 290 0 0 0;
+#X floatatom 56 338 0 0 0;
+#X floatatom 56 221 0 0 0;
+#X msg 102 280 4 \$1;
+#X msg 103 312 5 \$1;
+#X msg 101 335 6 \$1;
+#X msg 101 358 7 \$1;
+#X text 57 7 The beginnig of a dynamic mixer matrix object \, implemented
+together with Oswald;
+#X connect 0 0 2 0;
+#X connect 2 0 21 0;
+#X connect 3 0 4 0;
+#X connect 4 0 21 1;
+#X connect 5 0 6 0;
+#X connect 6 0 21 2;
+#X connect 7 0 8 0;
+#X connect 8 0 21 3;
+#X connect 9 0 3 0;
+#X connect 10 0 5 0;
+#X connect 11 0 7 0;
+#X connect 12 0 0 0;
+#X connect 13 0 21 0;
+#X connect 14 0 21 0;
+#X connect 15 0 21 0;
+#X connect 16 0 13 0;
+#X connect 17 0 14 0;
+#X connect 18 0 15 0;
+#X connect 19 0 20 0;
+#X connect 20 0 21 0;
+#X connect 21 0 1 0;
+#X connect 21 0 1 1;
+#X connect 22 0 23 0;
+#X connect 23 0 21 4;
+#X connect 24 0 25 0;
+#X connect 25 0 21 5;
+#X connect 26 0 27 0;
+#X connect 27 0 21 6;
+#X connect 28 0 29 0;
+#X connect 29 0 21 7;
+#X connect 30 0 24 0;
+#X connect 31 0 26 0;
+#X connect 32 0 28 0;
+#X connect 33 0 22 0;
+#X connect 34 0 39 0;
+#X connect 35 0 40 0;
+#X connect 36 0 41 0;
+#X connect 37 0 38 0;
+#X connect 38 0 21 0;
+#X connect 39 0 21 0;
+#X connect 40 0 21 0;
+#X connect 41 0 21 0;
diff --git a/signal/pipewrite~.c b/signal/pipewrite~.c
new file mode 100755
index 0000000..fe332f8
--- /dev/null
+++ b/signal/pipewrite~.c
@@ -0,0 +1,216 @@
+/* (C) Guenter Geiger <geiger@epy.co.at> */
+
+
+#include "m_imp.h"
+//#include <m_pd.h>
+#include "g_canvas.h"
+#ifdef NT
+#pragma warning( disable : 4244 )
+#pragma warning( disable : 4305 )
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <signal.h>
+
+/*
+ * -------------------------- pipewrite~ -------------------------------
+ */
+
+#define MAX_CHANS 4
+#define BLOCKTIME 0.001
+#define uint32 unsigned int
+#define uint16 unsigned short
+
+static t_class *pipewrite_class;
+
+typedef struct _pipewrite
+{
+ t_object x_obj;
+ t_symbol* filename;
+ int x_file;
+ t_int x_channels;
+ t_int size;
+ t_glist * x_glist;
+ t_int x_blocked;
+ t_int x_blockwarn;
+ short maxval;
+} t_pipewrite;
+
+static void pipewrite_close(t_pipewrite *x)
+{
+ if (x->x_file > 0) {
+ close(x->x_file);
+ }
+ x->x_file = -1;
+ x->size=0;
+}
+
+
+static void pipewrite_open(t_pipewrite *x,t_symbol *filename)
+{
+ char fname[MAXPDSTRING];
+
+ if (filename == &s_) {
+ post("pipewrite: open without filename");
+ return;
+ }
+
+ canvas_makefilename(glist_getcanvas(x->x_glist), filename->s_name,
+ fname, MAXPDSTRING);
+ x->x_blocked = 0;
+ x->filename = filename;
+ x->maxval=0;
+ x->size=0;
+ post("pipewrite: filename = %s",x->filename->s_name);
+
+ pipewrite_close(x);
+
+ if ((x->x_file = open(fname,O_WRONLY | O_NONBLOCK)) < 0)
+ {
+
+ error("can't open pipe %s: ",fname);
+ perror("system says");
+ return;
+ }
+}
+
+static void pipewrite_block(t_pipewrite *x, t_floatarg f)
+{
+ x->x_blockwarn = f;
+}
+
+
+static short out[4*64];
+
+static t_int *pipewrite_perform(t_int *w)
+{
+ t_pipewrite* x = (t_pipewrite*)(w[1]);
+ t_float * in[4];
+ int c = x->x_channels;
+ int i,num,n;
+ short* tout = out;
+ int ret;
+ double timebefore,timeafter;
+ double late;
+ struct sigaction action;
+ struct sigaction oldaction;
+
+
+ if (x->x_file < 0) {
+ pipewrite_open(x,x->filename);
+ }
+
+ action.sa_handler = SIG_IGN;
+ sigaction(SIGPIPE, &action, &oldaction);
+
+ for (i=0;i < c;i++) {
+ in[i] = (t_float *)(w[2+i]);
+ }
+
+ n = num = (int)(w[2+c]);
+
+ /* loop */
+
+ if (x->x_file >= 0) {
+
+ while (n--) {
+ for (i=0;i<c;i++) {
+ if (*(in[i]) > 1. ) { *(in[i]) = 1. ; }
+ if (*(in[i]) < -1. ) { *(in[i]) = -1. ; }
+ *tout++ = (*(in[i])++ * 32768.);
+ }
+ }
+
+ timebefore = sys_getrealtime();
+ if ((ret = write(x->x_file,out,sizeof(short)*num*c)) < sizeof(short)*num*c) {
+ post("pipewrite: short write %d",ret);
+
+ }
+
+ timeafter = sys_getrealtime();
+ late = timeafter - timebefore;
+ x->size +=ret;
+ /* OK, we let only 10 ms block here */
+ if (late > BLOCKTIME && x->x_blockwarn) {
+ x->x_blocked++;
+ if (x->x_blocked > x->x_blockwarn) {
+ x->x_blocked=0;
+/* post("maximum blockcount %d reached",x->x_blockwarn); */
+ }
+ }
+ }
+
+ sigaction(SIGPIPE, &oldaction, NULL);
+
+ return (w+3+c);
+}
+
+
+
+static void pipewrite_dsp(t_pipewrite *x, t_signal **sp)
+{
+ switch (x->x_channels) {
+ case 1:
+ dsp_add(pipewrite_perform, 3, x, sp[0]->s_vec,
+ sp[0]->s_n);
+ break;
+ case 2:
+ dsp_add(pipewrite_perform, 4, x, sp[0]->s_vec,
+ sp[1]->s_vec, sp[0]->s_n);
+ break;
+ case 4:
+ dsp_add(pipewrite_perform, 6, x, sp[0]->s_vec,
+ sp[1]->s_vec,
+ sp[2]->s_vec,
+ sp[3]->s_vec,
+ sp[0]->s_n);
+ break;
+ }
+}
+
+static void pipewrite_free(t_pipewrite* x)
+{
+ pipewrite_close(x);
+}
+
+
+static void *pipewrite_new(t_symbol* name,t_floatarg chan)
+{
+ t_pipewrite *x = (t_pipewrite *)pd_new(pipewrite_class);
+ t_int c = chan;
+
+ if (c<1 || c > MAX_CHANS) c = 1;
+
+ x->x_glist = (t_glist*) canvas_getcurrent();
+ x->x_channels = c--;
+ post("channels:%d",x->x_channels);
+ x->x_file=0;
+ x->x_blocked = 0;
+ x->x_blockwarn = 10;
+ while (c--) {
+ inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal);
+ }
+
+ if (name && name != &s_) { /* start the pipe */
+ pipewrite_open(x,name);
+ }
+
+ return (x);
+}
+
+void pipewrite_tilde_setup(void)
+{
+ pipewrite_class = class_new(gensym("pipewrite~"), (t_newmethod)pipewrite_new, (t_method)pipewrite_free,
+ sizeof(t_pipewrite), 0,A_DEFSYM,A_DEFFLOAT,A_NULL);
+ class_addmethod(pipewrite_class,nullfn,gensym("signal"), 0);
+ class_addmethod(pipewrite_class, (t_method) pipewrite_dsp, gensym("dsp"), 0);
+ class_addmethod(pipewrite_class, (t_method) pipewrite_open, gensym("open"), A_SYMBOL,A_NULL);
+ class_addmethod(pipewrite_class, (t_method) pipewrite_close, gensym("close"), 0);
+ class_addmethod(pipewrite_class, (t_method)pipewrite_block,gensym("block"),A_DEFFLOAT,0);
+
+}
diff --git a/signal/rtin~.c b/signal/rtin~.c
new file mode 100755
index 0000000..d086003
--- /dev/null
+++ b/signal/rtin~.c
@@ -0,0 +1,76 @@
+/* (C) Guenter Geiger <geiger@epy.co.at> */
+
+
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #include <fcntl.h>
+ #include <sys/time.h>
+ #include <unistd.h>
+
+// int gettimeofday(struct timeval *tv, struct timezone *tz);
+
+
+
+#include "math.h"
+#include <m_pd.h>
+
+
+/* ----------------------------- rtin ----------------------------- */
+static t_class *rtin_class;
+
+
+#define INVTWOPI 0.15915494f
+
+typedef struct _rtin
+{
+ t_object x_obj;
+ t_int fd;
+ t_int usec;
+} t_rtin;
+
+static void *rtin_new(t_symbol *s, int argc, t_atom *argv)
+{
+ t_rtin *x = (t_rtin *)pd_new(rtin_class);
+ /* inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal);*/
+ outlet_new(&x->x_obj, &s_float);
+
+ x->usec=0;
+ x->fd = open("/dev/midi00",O_RDWR|O_NDELAY);
+
+ return (x);
+
+}
+
+t_int *rtin_perform(t_int *w)
+{
+ struct timeval tv;
+ long diff;
+ t_rtin* x = (t_rtin *)(w[1]);
+// int n = (int)(w[2]);
+ char c;
+
+
+ if (read(x->fd,&c,1) == 1) {
+ gettimeofday(&tv, NULL);
+ diff = tv.tv_usec - x->usec;
+ if (diff < 0) diff+=1000000;
+ if (diff > 10000) outlet_float(x->x_obj.ob_outlet,diff*0.001);
+ x->usec=tv.tv_usec;
+ }
+
+
+ return (w+2);
+}
+
+static void rtin_dsp(t_rtin *x, t_signal **sp)
+{
+ dsp_add(rtin_perform, 1, x);
+}
+
+void rtin_tilde_setup(void)
+{
+ rtin_class = class_new(gensym("rtin~"), (t_newmethod)rtin_new, 0,
+ sizeof(t_rtin), 0, A_GIMME, 0);
+ class_addmethod(rtin_class, nullfn, gensym("signal"), 0);
+ class_addmethod(rtin_class, (t_method)rtin_dsp, gensym("dsp"), 0);
+}
diff --git a/signal/rtin~.pd b/signal/rtin~.pd
new file mode 100755
index 0000000..176be1a
--- /dev/null
+++ b/signal/rtin~.pd
@@ -0,0 +1,32 @@
+#N canvas 321 9 450 300 10;
+#X obj 121 96 noise~;
+#X obj 139 202 dac~;
+#X obj 152 157 *~;
+#X obj 210 121 line~;
+#X msg 175 34 bang;
+#X obj 332 193 print;
+#X msg 141 69 1 \, 0 10;
+#X obj 270 89 int;
+#X obj 329 86 + 1;
+#X obj 263 141 sel 0;
+#X floatatom 274 167 5 0 0;
+#X obj 366 82 metro 20;
+#X floatatom 355 52 5 0 0;
+#X obj 270 110 % 8;
+#X obj 227 15 rtin~;
+#X msg 231 48 bang;
+#X connect 0 0 2 0;
+#X connect 2 0 1 0;
+#X connect 2 0 1 1;
+#X connect 3 0 2 1;
+#X connect 4 0 6 0;
+#X connect 6 0 3 0;
+#X connect 7 0 13 0;
+#X connect 8 0 7 1;
+#X connect 9 0 6 0;
+#X connect 12 0 11 1;
+#X connect 13 0 8 0;
+#X connect 13 0 9 0;
+#X connect 13 0 10 0;
+#X connect 14 0 15 0;
+#X connect 15 0 7 0;
diff --git a/signal/sfread~.c b/signal/sfread~.c
new file mode 100755
index 0000000..6cb97ab
--- /dev/null
+++ b/signal/sfread~.c
@@ -0,0 +1,317 @@
+/* (C) Guenter Geiger <geiger@epy.co.at> */
+
+
+#include <m_imp.h>
+/*#include <m_pd.h>*/
+#include "g_canvas.h"
+#ifdef NT
+#pragma warning( disable : 4244 )
+#pragma warning( disable : 4305 )
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#ifndef NT
+#include <unistd.h>
+#include <sys/mman.h>
+#else
+#include <io.h>
+#endif
+
+
+#include <fcntl.h>
+#include <sys/stat.h>
+
+/* ------------------------ sfread~ ----------------------------- */
+
+#ifdef NT
+#define BINREADMODE "rb"
+#else
+#define BINREADMODE "r"
+#endif
+
+static t_class *sfread_class;
+
+
+typedef struct _sfread
+{
+ t_object x_obj;
+ void* x_mapaddr;
+ int x_fd;
+
+ t_int x_play;
+ t_int x_channels;
+ t_int x_size;
+ t_int x_loop;
+ t_float x_offset;
+ t_float x_skip;
+ t_float x_speed;
+
+ t_glist * x_glist;
+ t_outlet *x_bangout;
+} t_sfread;
+
+
+void sfread_open(t_sfread *x,t_symbol *filename)
+{
+ struct stat fstate;
+ char fname[MAXPDSTRING];
+
+ if (filename == &s_) {
+ post("sfread: open without filename");
+ return;
+ }
+
+ canvas_makefilename(glist_getcanvas(x->x_glist), filename->s_name,
+ fname, MAXPDSTRING);
+
+
+ /* close the old file */
+
+ if (x->x_mapaddr) munmap(x->x_mapaddr,x->x_size);
+ if (x->x_fd >= 0) close(x->x_fd);
+
+ if ((x->x_fd = open(fname,O_RDONLY)) < 0)
+ {
+ error("can't open %s",fname);
+ x->x_play = 0;
+ x->x_mapaddr = NULL;
+ return;
+ }
+
+ /* get the size */
+
+ fstat(x->x_fd,&fstate);
+ x->x_size = fstate.st_size;
+
+ /* map the file into memory */
+
+ if (!(x->x_mapaddr = mmap(NULL,x->x_size,PROT_READ,MAP_PRIVATE,x->x_fd,0)))
+ {
+ error("can't mmap %s",fname);
+ return;
+ }
+}
+
+#define MAX_CHANS 4
+
+static t_int *sfread_perform(t_int *w)
+{
+ t_sfread* x = (t_sfread*)(w[1]);
+ short* buf = x->x_mapaddr;
+/* t_float *in = (t_float *)(w[2]); will we need this (indexing) ?*/
+ int c = x->x_channels;
+ t_float offset = x->x_offset*c;
+ t_float speed = x->x_speed;
+ int i,n;
+ int end = x->x_size/sizeof(short);
+ t_float* out[MAX_CHANS];
+
+ for (i=0;i<c;i++)
+ out[i] = (t_float *)(w[3+i]);
+ n = (int)(w[3+c]);
+
+ /* loop */
+
+ if (offset > end)
+ offset = end;
+
+ if (offset + n*c*speed > end) { // playing forward end
+ if (!x->x_loop) {
+ x->x_play=0;
+ offset = x->x_skip*c;
+ }
+ }
+
+ if (offset + n*c*speed < 0) { // playing backwards end
+ if (!x->x_loop) {
+ x->x_play=0;
+ offset = end;
+ }
+
+ }
+
+
+ if (x->x_play && x->x_mapaddr) {
+
+ if (speed != 1) { /* different speed */
+ float aoff = (((int)offset)>>1)<<1;
+ while (n--) {
+ for (i=0;i<c;i++) {
+ *out[i]++ = *(buf+(int)aoff+i)*3.052689e-05;
+ }
+ offset+=speed*c;
+ aoff = (((int)offset)>>1)<<1;
+ if (aoff > end) {
+ if (x->x_loop) aoff = x->x_skip;
+ else break;
+ }
+ if (aoff < 0) {
+ if (x->x_loop) aoff = end;
+ else break;
+ }
+ }
+ /* Fill with zero in case of end */
+ n++;
+ while (n--)
+ for (i=0;i<c;i++)
+ *out[i]++ = 0;
+ offset = aoff;
+ }
+ else { /* speed == 1 */
+ int aoff = (((int)offset)>>1)<<1;
+ while (n--) {
+ for (i=0;i<c;i++) {
+ *out[i]++ = *(buf+aoff+i)*3.052689e-05;
+ }
+ aoff+=c;
+ if (aoff > end) {
+ if (x->x_loop) aoff = x->x_skip;
+ else break;
+ }
+ }
+
+ /* Fill with zero in case of end */
+ n++;
+ while (n--)
+ for (i=0;i<c;i++)
+ *out[i]++ = 0.;
+ offset = aoff;
+ }
+
+ }
+ else {
+ while (n--) {
+ for (i=0;i<c;i++)
+ *out[i]++ = 0.;
+ }
+ }
+ x->x_offset = offset/c; /* this should always be integer !! */
+ return (w+c+4);
+}
+
+
+static void sfread_float(t_sfread *x, t_floatarg f)
+{
+ int t = f;
+ if (t && x->x_mapaddr) {
+ x->x_play=1;
+ }
+ else {
+ x->x_play=0;
+ }
+
+}
+
+static void sfread_loop(t_sfread *x, t_floatarg f)
+{
+ x->x_loop = f;
+}
+
+
+
+static void sfread_size(t_sfread* x)
+{
+ t_atom a;
+
+ SETFLOAT(&a,x->x_size*0.5/x->x_channels);
+ outlet_list(x->x_bangout, gensym("size"),1,&a);
+}
+
+static void sfread_state(t_sfread* x)
+{
+ t_atom a;
+
+ SETFLOAT(&a,x->x_play);
+ outlet_list(x->x_bangout, gensym("state"),1,&a);
+}
+
+
+
+
+static void sfread_bang(t_sfread* x)
+{
+ x->x_offset = x->x_skip*x->x_channels;
+ sfread_float(x,1.0);
+}
+
+
+static void sfread_dsp(t_sfread *x, t_signal **sp)
+{
+/* post("sfread: dsp"); */
+ switch (x->x_channels) {
+ case 1:
+ dsp_add(sfread_perform, 4, x, sp[0]->s_vec,
+ sp[1]->s_vec, sp[0]->s_n);
+ break;
+ case 2:
+ dsp_add(sfread_perform, 5, x, sp[0]->s_vec,
+ sp[1]->s_vec,sp[2]->s_vec, sp[0]->s_n);
+ break;
+ case 4:
+ dsp_add(sfread_perform, 6, x, sp[0]->s_vec,
+ sp[1]->s_vec,sp[2]->s_vec,
+ sp[3]->s_vec,sp[4]->s_vec,
+ sp[0]->s_n);
+ break;
+ }
+}
+
+
+static void *sfread_new(t_floatarg chan,t_floatarg skip)
+{
+ t_sfread *x = (t_sfread *)pd_new(sfread_class);
+ t_int c = chan;
+
+ x->x_glist = (t_glist*) canvas_getcurrent();
+
+ if (c<1 || c > MAX_CHANS) c = 1;
+ floatinlet_new(&x->x_obj, &x->x_offset);
+ floatinlet_new(&x->x_obj, &x->x_speed);
+
+
+ x->x_fd = -1;
+ x->x_mapaddr = NULL;
+
+ x->x_size = 0;
+ x->x_loop = 0;
+ x->x_channels = c;
+ x->x_mapaddr=NULL;
+ x->x_offset = skip;
+ x->x_skip = skip;
+ x->x_speed = 1.0;
+ x->x_play = 0;
+
+ while (c--) {
+ outlet_new(&x->x_obj, gensym("signal"));
+ }
+
+ x->x_bangout = outlet_new(&x->x_obj, &s_float);
+
+/* post("sfread: x_channels = %d, x_speed = %f",x->x_channels,x->x_speed);*/
+
+ return (x);
+}
+
+void sfread_tilde_setup(void)
+{
+ /* sfread */
+
+ sfread_class = class_new(gensym("sfread~"), (t_newmethod)sfread_new, 0,
+ sizeof(t_sfread), 0,A_DEFFLOAT,A_DEFFLOAT,0);
+ class_addmethod(sfread_class, nullfn, gensym("signal"), 0);
+ class_addmethod(sfread_class, (t_method) sfread_dsp, gensym("dsp"), 0);
+ class_addmethod(sfread_class, (t_method) sfread_open, gensym("open"), A_SYMBOL,A_NULL);
+ class_addmethod(sfread_class, (t_method) sfread_size, gensym("size"), 0);
+ class_addmethod(sfread_class, (t_method) sfread_state, gensym("state"), 0);
+ class_addfloat(sfread_class, sfread_float);
+ class_addbang(sfread_class,sfread_bang);
+ class_addmethod(sfread_class,(t_method)sfread_loop,gensym("loop"),A_FLOAT,A_NULL);
+
+}
+
+
+
+
+
+
diff --git a/signal/sfread~.pd b/signal/sfread~.pd
new file mode 100755
index 0000000..5cc1058
--- /dev/null
+++ b/signal/sfread~.pd
@@ -0,0 +1,44 @@
+#N canvas 89 114 600 456 8;
+#X msg 34 135 bang;
+#X obj 228 324 dac~;
+#X msg 70 218 1;
+#X floatatom 348 128;
+#X text 14 33 file to open;
+#X text 33 116 start playback;
+#X msg 70 240 0;
+#X text 34 10 SFREAD;
+#X text 34 21 =======;
+#X text 346 96 playback speed (defaults to 1);
+#X text 93 8 The file should have the systems samplerate (44100) and endianess matching the machine.;
+#X text 25 257 pause on/off during playback;
+#X text 277 46 resets sound to position;
+#X msg 322 63 200;
+#X text 288 164 instatiation: sfread <channels> <skip>;
+#X text 276 35 start position in samples (defaults to <skip>);
+#X floatatom 231 102;
+#X msg 172 114 loop 1;
+#X msg 152 94 loop 0;
+#X msg 364 224 size;
+#X floatatom 336 275;
+#X text 333 205 Get the size (in frames);
+#X obj 207 164 sfread~ 2 62;
+#X msg 14 85 open \$1;
+#X obj 14 66 openpanel;
+#X msg 69 66 bang;
+#X msg 365 249 state;
+#X connect 0 0 22 0;
+#X connect 2 0 22 0;
+#X connect 3 0 22 2;
+#X connect 6 0 22 0;
+#X connect 13 0 22 1;
+#X connect 16 0 22 1;
+#X connect 17 0 22 0;
+#X connect 18 0 22 0;
+#X connect 19 0 22 0;
+#X connect 22 0 1 0;
+#X connect 22 1 1 1;
+#X connect 22 2 20 0;
+#X connect 23 0 22 0;
+#X connect 24 0 23 0;
+#X connect 25 0 24 0;
+#X connect 26 0 22 0;
diff --git a/signal/sfwrite.pd b/signal/sfwrite.pd
new file mode 100755
index 0000000..1426cf3
--- /dev/null
+++ b/signal/sfwrite.pd
@@ -0,0 +1,45 @@
+#N canvas 340 71 600 460 12;
+#X obj 185 96 sfwrite~ 2;
+#X msg 65 16 open test.wav;
+#X floatatom 185 16;
+#X msg 147 308 0;
+#X obj 232 17 adc~;
+#X msg 91 278 0;
+#X msg 59 278 1;
+#X obj 142 222 table;
+#X msg 136 171 bang;
+#X msg 32 171 resize 441000;
+#X msg 181 172 read16 test.wav 200 l;
+#X obj 417 104 env~;
+#X obj 298 34 osc~ 220;
+#X obj 125 396 dac~;
+#X floatatom 411 10;
+#X obj 125 341 sfread~ 2;
+#X obj 281 379 dbtorms;
+#X obj 281 279 slider 96 0 15;
+#X obj 159 372 *~ 0;
+#X obj 125 372 *~ 0;
+#X msg 125 277 open test.wav \, bang;
+#X floatatom 417 129;
+#X connect 1 0 0 0;
+#X connect 2 0 0 0;
+#X connect 3 0 15 1;
+#X connect 5 0 15 0;
+#X connect 6 0 15 0;
+#X connect 8 0 7 0;
+#X connect 9 0 7 0;
+#X connect 10 0 7 0;
+#X connect 11 0 21 0;
+#X connect 12 0 0 0;
+#X connect 12 0 0 1;
+#X connect 12 0 11 0;
+#X connect 12 0 19 0;
+#X connect 12 0 18 0;
+#X connect 14 0 12 0;
+#X connect 15 0 19 0;
+#X connect 15 1 18 0;
+#X connect 16 0 18 1;
+#X connect 16 0 19 1;
+#X connect 18 0 13 1;
+#X connect 19 0 13 0;
+#X connect 20 0 15 0;
diff --git a/signal/sfwrite~.c b/signal/sfwrite~.c
new file mode 100755
index 0000000..9a999c9
--- /dev/null
+++ b/signal/sfwrite~.c
@@ -0,0 +1,284 @@
+/* (C) Guenter Geiger <geiger@epy.co.at> */
+
+
+#include <m_imp.h>
+/*#include <m_pd.h>*/
+#include "g_canvas.h"
+#ifdef NT
+#pragma warning( disable : 4244 )
+#pragma warning( disable : 4305 )
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#ifndef NT
+#include <unistd.h>
+#include <sys/mman.h>
+#else
+#include <io.h>
+#endif
+#include <fcntl.h>
+#include <sys/stat.h>
+
+
+#ifdef NT
+#define BINREADMODE "rb"
+#define OPENPARAMS O_WRONLY | O_CREAT | O_TRUNC
+#else
+#define BINREADMODE "r"
+#define OPENPARAMS O_WRONLY | O_CREAT | O_NONBLOCK | O_TRUNC
+#endif
+#define MAX_CHANS 4
+
+
+/*
+ * ------------------------------------------- sfwrite~ -------------------------------
+ */
+
+#define BLOCKTIME 0.01
+#define uint32 unsigned int
+#define uint16 unsigned short
+
+static t_class *sfwrite_class;
+
+typedef struct _sfwrite
+{
+ t_object x_obj;
+ t_symbol* filename;
+ int x_file;
+
+ t_int rec;
+ t_int x_channels;
+ uint32 size;
+ t_glist * x_glist;
+ t_int x_blocked;
+ t_int x_blockwarn;
+} t_sfwrite;
+
+typedef struct _wave
+{
+ char w_fileid[4]; /* chunk id 'RIFF' */
+ uint32 w_chunksize; /* chunk size */
+ char w_waveid[4]; /* wave chunk id 'WAVE' */
+ char w_fmtid[4]; /* format chunk id 'fmt ' */
+ uint32 w_fmtchunksize; /* format chunk size */
+ uint16 w_fmttag; /* format tag, 1 for PCM */
+ uint16 w_nchannels; /* number of channels */
+ uint32 w_samplespersec; /* sample rate in hz */
+ uint32 w_navgbytespersec; /* average bytes per second */
+ uint16 w_nblockalign; /* number of bytes per sample */
+ uint16 w_nbitspersample; /* number of bits in a sample */
+ char w_datachunkid[4]; /* data chunk id 'data' */
+ uint32 w_datachunksize; /* length of data chunk */
+} t_wave;
+
+
+static void sfwrite_wave_setup(t_sfwrite* x,t_wave* w)
+{
+
+ strncpy(w->w_fileid,"RIFF",4); /* chunk id 'RIFF' */
+ w->w_chunksize = x->size + sizeof(t_wave) -8; /* chunk size */
+ strncpy(w->w_waveid,"WAVE",4); /* wave chunk id 'WAVE' */
+ strncpy(w->w_fmtid,"fmt ",4); /* format chunk id 'fmt '*/
+ w->w_fmtchunksize = 16; /* format chunk size */
+ w->w_fmttag = 1; /* format tag, 1 for PCM */
+ w->w_nchannels = x->x_channels; /* number of channels */
+ w->w_samplespersec = 44100; /* sample rate in hz */
+ w->w_navgbytespersec = 44100*x->x_channels*2; /* average bytes per second */
+ w->w_nblockalign = 4; /* number of bytes per sample */
+ w->w_nbitspersample = 16; /* number of bits in a sample */
+ strncpy(w->w_datachunkid,"data",4); /* data chunk id 'data'*/
+ w->w_datachunksize = x->size; /* length of data chunk */
+}
+
+
+
+static void sfwrite_close(t_sfwrite *x)
+{
+ if (x->x_file > 0) {
+ t_wave w;
+ sfwrite_wave_setup(x,&w);
+ lseek(x->x_file,0,SEEK_SET);
+ write(x->x_file,&w,sizeof(w));
+ close(x->x_file);
+ }
+ x->x_file = -1;
+}
+
+
+static void sfwrite_open(t_sfwrite *x,t_symbol *filename)
+{
+ char fname[MAXPDSTRING];
+
+ if (filename == &s_) {
+ post("sfwrite: open without filename");
+ return;
+ }
+
+ canvas_makefilename(glist_getcanvas(x->x_glist), filename->s_name,
+ fname, MAXPDSTRING);
+
+ x->x_blocked = 0;
+ x->filename = filename;
+ post("sfwrite: filename = %s",x->filename->s_name);
+
+ sfwrite_close(x);
+
+ if ((x->x_file = open(fname,OPENPARAMS,0664)) < 0)
+ {
+ error("can't create %s",fname);
+ return;
+ }
+
+ /* skip the header */
+
+ lseek(x->x_file,sizeof(t_wave),SEEK_SET);
+ x->size = 0;
+
+
+}
+
+static void sfwrite_block(t_sfwrite *x, t_floatarg f)
+{
+ x->x_blockwarn = f;
+}
+
+
+static void sfwrite_float(t_sfwrite *x, t_floatarg f)
+{
+ int t = f;
+ if (t) {
+ post("sfwrite: start", f);
+ x->rec=1;
+ }
+ else {
+ post("sfwrite: stop", f);
+ x->rec=0;
+ }
+
+}
+
+
+static short out[4*64];
+
+static t_int *sfwrite_perform(t_int *w)
+{
+ t_sfwrite* x = (t_sfwrite*)(w[1]);
+ t_float * in[4];
+ int c = x->x_channels;
+ int i,num,n;
+ short* tout = out;
+ int ret;
+ double timebefore,timeafter;
+ double late;
+
+ for (i=0;i < c;i++) {
+ in[i] = (t_float *)(w[2+i]);
+ }
+
+ n = num = (int)(w[2+c]);
+
+ /* loop */
+
+ if (x->rec && x->x_file) {
+
+ while (n--) {
+ for (i=0;i<c;i++) {
+ *tout++ = *(in[i])++ * 32768.;
+ }
+ }
+
+ timebefore = sys_getrealtime();
+ if ((ret =write(x->x_file,out,sizeof(short)*num*c)) < (signed int)sizeof(short)*num*c) {
+ post("sfwrite: short write %d",ret);
+
+ }
+ timeafter = sys_getrealtime();
+ late = timeafter - timebefore;
+
+ /* OK, we let only 10 ms block here */
+ if (late > BLOCKTIME && x->x_blockwarn) {
+ post("sfwrite blocked %f ms",late*1000);
+ x->x_blocked++;
+ if (x->x_blocked > x->x_blockwarn) {
+ x->rec = 0;
+ post("maximum blockcount %d reached, recording stopped (set blockcount with \"block <num>\"",x->x_blockwarn);
+ }
+ }
+ x->size +=64*x->x_channels*sizeof(short) ;
+ }
+
+ return (w+3+c);
+}
+
+
+
+static void sfwrite_dsp(t_sfwrite *x, t_signal **sp)
+{
+ switch (x->x_channels) {
+ case 1:
+ dsp_add(sfwrite_perform, 3, x, sp[0]->s_vec,
+ sp[0]->s_n);
+ break;
+ case 2:
+ dsp_add(sfwrite_perform, 4, x, sp[0]->s_vec,
+ sp[1]->s_vec, sp[0]->s_n);
+ break;
+ case 4:
+ dsp_add(sfwrite_perform, 6, x, sp[0]->s_vec,
+ sp[1]->s_vec,
+ sp[2]->s_vec,
+ sp[3]->s_vec,
+ sp[0]->s_n);
+ break;
+ }
+}
+
+static void sfwrite_free(t_sfwrite* x)
+{
+ sfwrite_close(x);
+}
+
+
+static void *sfwrite_new(t_floatarg chan)
+{
+ t_sfwrite *x = (t_sfwrite *)pd_new(sfwrite_class);
+ t_int c = chan;
+
+ if (c<1 || c > MAX_CHANS) c = 1;
+
+ x->x_glist = (t_glist*) canvas_getcurrent();
+ x->x_channels = c--;
+ x->x_file=0;
+ x->rec = 0;
+ x->size = 0;
+ x->x_blocked = 0;
+ x->x_blockwarn = 10;
+ while (c--) {
+ inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal);
+ }
+
+
+ return (x);
+}
+
+void sfwrite_tilde_setup(void)
+{
+ sfwrite_class = class_new(gensym("sfwrite~"), (t_newmethod)sfwrite_new, (t_method)sfwrite_free,
+ sizeof(t_sfwrite), 0,A_DEFFLOAT,0);
+ class_addmethod(sfwrite_class,nullfn,gensym("signal"), 0);
+ class_addmethod(sfwrite_class, (t_method) sfwrite_dsp, gensym("dsp"), 0);
+ class_addmethod(sfwrite_class, (t_method) sfwrite_open, gensym("open"), A_SYMBOL,A_NULL);
+ class_addmethod(sfwrite_class, (t_method) sfwrite_close, gensym("close"), 0);
+ class_addmethod(sfwrite_class, (t_method)sfwrite_block,gensym("block"),A_DEFFLOAT,0);
+ class_addfloat(sfwrite_class, sfwrite_float);
+
+}
+
+
+
+
+
+
+
+
diff --git a/signal/stream.h b/signal/stream.h
new file mode 100755
index 0000000..331cf30
--- /dev/null
+++ b/signal/stream.h
@@ -0,0 +1,30 @@
+/* (C) Guenter Geiger 1999 */
+
+#define SF_FLOAT 1
+#define SF_DOUBLE 2
+#define SF_8BIT 10
+#define SF_16BIT 11
+#define SF_32BIT 12
+#define SF_ALAW 20
+#define SF_MP3 30
+
+#define SF_SIZEOF(a) (a == SF_FLOAT ? sizeof(t_float) : \
+ a == SF_16BIT ? sizeof(short) : 1)
+
+
+
+typedef struct _tag { /* size (bytes) */
+ char version; /* 1 */
+ char format; /* 1 */
+ int count; /* 4 */
+ char channels; /* 1 */
+ int framesize; /* 4 */
+ char extension[5]; /* 5 */
+} t_tag; /*--------------*/
+ /* 16 */
+
+
+typedef struct _frame {
+ t_tag tag;
+ char* data;
+} t_frame;
diff --git a/signal/streamin~.c b/signal/streamin~.c
new file mode 100755
index 0000000..54ab283
--- /dev/null
+++ b/signal/streamin~.c
@@ -0,0 +1,404 @@
+
+/* Written by Guenter Geiger <geiger@debian.org> (C) 1999 */
+
+#include <m_pd.h>
+#include "stream.h"
+
+#include <sys/types.h>
+#include <string.h>
+#ifdef unix
+#include <sys/socket.h>
+#include <errno.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <netdb.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <fcntl.h>
+#define SOCKET_ERROR -1
+#else
+#include <winsock.h>
+#endif
+
+
+
+#ifdef NT
+#pragma warning( disable : 4244 )
+#pragma warning( disable : 4305 )
+#endif
+
+#ifdef unix
+#define NONBLOCKED
+#endif
+#define INBUFSIZE 8192
+#define MAXFRAMES 128
+#define MAXFRAMESIZE 256
+#define AVERAGENUM 10
+
+/*#define DEBUGMESS(x) x*/
+#define DEBUGMESS(x)
+
+/* Utility functions */
+
+/* TODO !!!!
+ - check udp support
+*/
+
+
+#ifdef NT
+extern int close(int);
+extern void sys_rmpollfn(int fd);
+extern sys_addpollfn(int fd, void* fn, void *ptr);
+#endif
+
+static void sys_sockerror(char *s)
+{
+#ifdef unix
+ int err = errno;
+#else
+ int err = WSAGetLastError();
+ if (err == 10054) return;
+#endif
+ post("%s: %s (%d)\n", s, strerror(err), err);
+}
+
+
+static void sys_closesocket(int fd)
+{
+#ifdef UNIX
+ close(fd);
+#endif
+#ifdef NT
+ closesocket(fd);
+#endif
+}
+
+
+int setsocketoptions(int sockfd)
+{
+#ifdef unix
+ int sockopt = 1;
+ if (setsockopt(sockfd, SOL_TCP, TCP_NODELAY, (const char*) &sockopt, sizeof(int)) < 0)
+ DEBUGMESS(post("setsockopt NODELAY failed\n"));
+ else
+ DEBUGMESS(post("TCP_NODELAY set"));
+
+ /* if we don`t use REUSEADDR we have to wait under unix until the
+ address gets freed after a close ... this can be very annoying
+ when working with netsend/netreceive GG
+ */
+
+ sockopt = 1;
+ if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(int)) < 0)
+ post("setsockopt failed\n");
+#endif
+ return 0;
+}
+
+
+
+/* ------------------------ streamin~ ----------------------------- */
+
+
+static t_class *streamin_class;
+
+
+
+typedef struct _streamin
+{
+ t_object x_obj;
+ int x_socket;
+ int x_connectsocket;
+ int x_nconnections;
+ int x_ndrops;
+ int x_fd;
+ int x_tcp;
+
+ /* buffering */
+
+ int framein;
+ int frameout;
+ t_frame frames[MAXFRAMES];
+ int maxframes;
+
+ int nbytes;
+ int counter;
+ int average[AVERAGENUM];
+ int averagecur;
+ int underflow;
+} t_streamin;
+
+
+
+
+static void streamin_datapoll(t_streamin *x)
+{
+ int ret;
+ int n;
+ t_tag tag;
+ int i;
+
+ n = x->nbytes;
+ if (x->nbytes == 0) { /* get the new tag */
+ ret = recv(x->x_socket, (char*) &x->frames[x->framein].tag,sizeof(t_tag),MSG_PEEK);
+ if (ret != sizeof(t_tag)) return;
+ ret = recv(x->x_socket, (char*) &x->frames[x->framein].tag,sizeof(t_tag),0);
+
+ x->nbytes = n = x->frames[x->framein].tag.framesize;
+ }
+
+ ret = recv(x->x_socket, (char*) x->frames[x->framein].data + x->frames[x->framein].tag.framesize - n, n, 0);
+ if (ret > 0)
+ n-=ret;
+
+ x->nbytes = n;
+ if (n == 0) {
+ x->counter++;
+ x->framein++;
+ x->framein %= MAXFRAMES;
+ }
+}
+
+static void streamin_reset(t_streamin* x,t_floatarg frames)
+{
+ int i;
+ x->counter = 0;
+ x->nbytes = 0;
+ x->framein = 0;
+ x->frameout = 0;
+ for (i=0;i<AVERAGENUM;i++)
+ x->average[i] = x->maxframes;
+ x->averagecur=0;
+ if (frames == 0.0)
+ x->maxframes = MAXFRAMES/2;
+ else
+ x->maxframes = frames;
+ x->underflow = 0;
+}
+
+
+static void streamin_connectpoll(t_streamin *x)
+{
+ int fd = accept(x->x_connectsocket, 0, 0);
+
+#ifdef NONBLOCKED
+ fcntl(fd,F_SETFL,O_NONBLOCK);
+#endif
+ if (fd < 0) {
+ post("streamin~: accept failed");
+ return;
+ }
+
+ if (x->x_socket > 0) {
+ post("streamin~: new connection");
+ close(x->x_socket);
+ sys_rmpollfn(x->x_socket);
+ }
+
+ streamin_reset(x,0);
+ x->x_socket = fd;
+ sys_addpollfn(fd, streamin_datapoll, x);
+}
+
+
+static int streamin_createsocket(t_streamin* x, int portno,t_symbol* prot)
+{
+ struct sockaddr_in server;
+ int sockfd;
+ int tcp = x->x_tcp;
+
+ /* create a socket */
+ if (!tcp)
+ sockfd = socket(AF_INET, SOCK_DGRAM, 0);
+ else
+ sockfd = socket(AF_INET, SOCK_STREAM, 0);
+
+ if (sockfd < 0)
+ {
+ sys_sockerror("socket");
+ return (0);
+ }
+ server.sin_family = AF_INET;
+ server.sin_addr.s_addr = INADDR_ANY;
+
+ /* assign server port number */
+
+ server.sin_port = htons((u_short)portno);
+ post("listening to port number %d", portno);
+
+
+ setsocketoptions(sockfd);
+
+
+ /* name the socket */
+
+ if (bind(sockfd, (struct sockaddr *)&server, sizeof(server)) < 0) {
+ sys_sockerror("bind");
+ sys_closesocket(sockfd);
+ return (0);
+ }
+
+
+ if (!tcp) {
+ x->x_socket = sockfd;
+ x->nbytes = 0;
+ sys_addpollfn(sockfd, streamin_datapoll, x);
+ }
+ else {
+ if (listen(sockfd, 5) < 0) {
+ sys_sockerror("listen");
+ sys_closesocket(sockfd);
+ }
+ else {
+ x->x_connectsocket = sockfd;
+ sys_addpollfn(sockfd, streamin_connectpoll, x);
+ }
+ }
+ return 1;
+}
+
+
+
+static void streamin_free(t_streamin *x)
+{
+ if (x->x_connectsocket > 0) {
+ sys_closesocket(x->x_connectsocket);
+ sys_rmpollfn(x->x_connectsocket);
+ }
+ sys_rmpollfn(x->x_socket);
+ sys_closesocket(x->x_socket);
+}
+
+
+#define QUEUESIZE ((x->framein + MAXFRAMES - x->frameout)%MAXFRAMES)
+
+static t_int *streamin_perform(t_int *w)
+{
+ t_streamin *x = (t_streamin*) (w[1]);
+ t_float *out = (t_float *)(w[2]);
+ int n = (int)(w[3]);
+ int ret;
+ int i = 0;
+
+ if (x->counter < x->maxframes) {
+ return (w+4);
+ }
+
+ if (x->framein == x->frameout) {
+ x->underflow++;
+ return w+4;
+ }
+
+
+ /* queue balancing */
+
+ x->average[x->averagecur] = QUEUESIZE;
+ x->averagecur++;
+ x->averagecur %= AVERAGENUM;
+
+ switch (x->frames[x->frameout].tag.format) {
+ case SF_FLOAT: {
+ t_float* buf = (t_float*)(x->frames[x->frameout].data);
+ while (n--)
+ *out++ = *buf++;
+ x->frameout++;
+ x->frameout %= MAXFRAMES;
+ break;
+ }
+ case SF_16BIT:
+ {
+ short* buf = (short*)(x->frames[x->frameout].data);
+
+ while (n--)
+ *out++ = (float) *buf++*3.051850e-05;
+ x->frameout++;
+ x->frameout %= MAXFRAMES;
+
+ break;
+ }
+ case SF_8BIT:
+ {
+ unsigned char* buf = (char*)(x->frames[x->frameout].data);
+
+ while (n--)
+ *out++ = (float) (0.0078125 * (*buf++)) - 1.0;
+ x->frameout++;
+ x->frameout %= MAXFRAMES;
+ break;
+ }
+ default:
+ post("unknown format %d",x->frames[x->frameout].tag.format);
+ break;
+ }
+
+ return (w+4);
+}
+
+
+
+static void streamin_dsp(t_streamin *x, t_signal **sp)
+{
+ dsp_add(streamin_perform, 3, x, sp[0]->s_vec, sp[0]->s_n);
+}
+
+
+static void streamin_print(t_streamin* x)
+{
+ int i;
+ int avg = 0;
+ for (i=0;i<AVERAGENUM;i++)
+ avg += x->average[i];
+ post("last size = %d, avg size = %d, %d underflows",
+ QUEUESIZE,avg,x->underflow);
+}
+
+
+
+
+static void *streamin_new(t_floatarg fportno, t_floatarg prot)
+{
+ t_streamin *x;
+ int i;
+
+ post("port %f",fportno);
+ x = (t_streamin *)pd_new(streamin_class);
+
+ x->x_connectsocket = -1;
+ x->x_socket = -1;
+ x->x_tcp = 1;
+ outlet_new(&x->x_obj, &s_signal);
+ x->x_nconnections = 0;
+ x->x_ndrops = 0;
+
+ for (i=0;i<MAXFRAMES;i++) {
+ x->frames[i].data = getbytes(MAXFRAMESIZE);
+ }
+ x->framein = 0;
+ x->frameout = 0;
+ x->maxframes = MAXFRAMES/2;
+
+ if (prot)
+ x->x_tcp = 0;
+
+ streamin_createsocket(x, fportno, gensym("tcp"));
+
+ return (x);
+}
+
+
+
+
+
+void streamin_tilde_setup(void)
+{
+ streamin_class = class_new(gensym("streamin~"),
+ (t_newmethod) streamin_new, (t_method) streamin_free,
+ sizeof(t_streamin), 0, A_DEFFLOAT,A_DEFFLOAT, A_NULL);
+
+ class_addmethod(streamin_class, nullfn, gensym("signal"), 0);
+ class_addmethod(streamin_class, (t_method) streamin_dsp, gensym("dsp"), 0);
+ class_addmethod(streamin_class, (t_method) streamin_print,
+ gensym("print"), 0);
+ class_addmethod(streamin_class, (t_method) streamin_reset,
+ gensym("reset"),A_DEFFLOAT, 0);
+}
diff --git a/signal/streamin~.pd b/signal/streamin~.pd
new file mode 100755
index 0000000..e248f27
--- /dev/null
+++ b/signal/streamin~.pd
@@ -0,0 +1,41 @@
+#N canvas 248 65 623 459 12;
+#X obj 49 95 print~;
+#X msg 49 67 bang;
+#X obj 27 24 streamin~ 3000;
+#X obj 132 210 streamout~;
+#X msg 132 108 disconnect;
+#X obj 372 72 osc~;
+#X obj 372 47 sig~ 220;
+#X floatatom 372 20 0 0 0;
+#X msg 285 162 format float;
+#X msg 284 184 format 16bit;
+#X text 14 432 (C) 1999 Guenter Geiger;
+#X msg 286 204 format 8bit;
+#X floatatom 132 235 0 0 0;
+#X text 21 295 The streamin~ object just takes the portnumber it is
+listening to as it's argument.;
+#X text 23 334 For help on the streamout object \, see the streamout.pd
+patch.;
+#X obj 27 159 dac~;
+#X obj 355 115 *~ 0.1;
+#X floatatom 418 88 0 0 0;
+#X floatatom 149 159 0 0 0;
+#X msg 285 252 connect gige 3001;
+#X msg 132 86 connect localhost 3000;
+#X connect 1 0 0 0;
+#X connect 2 0 0 0;
+#X connect 2 0 15 0;
+#X connect 2 0 15 1;
+#X connect 3 0 12 0;
+#X connect 4 0 3 0;
+#X connect 5 0 16 0;
+#X connect 6 0 5 0;
+#X connect 7 0 6 0;
+#X connect 8 0 3 0;
+#X connect 9 0 3 0;
+#X connect 11 0 3 0;
+#X connect 16 0 3 0;
+#X connect 17 0 16 1;
+#X connect 18 0 3 0;
+#X connect 19 0 3 0;
+#X connect 20 0 3 0;
diff --git a/signal/streamout~.c b/signal/streamout~.c
new file mode 100755
index 0000000..6e76b36
--- /dev/null
+++ b/signal/streamout~.c
@@ -0,0 +1,323 @@
+
+/* (C) Guenter Geiger <geiger@epy.co.at> */
+
+#include <m_pd.h>
+#include "stream.h"
+
+#include <sys/types.h>
+#include <string.h>
+#include <stdlib.h>
+#ifdef unix
+#include <errno.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#define SOCKET_ERROR -1
+#else
+#include <winsock.h>
+#endif
+
+#ifdef NT
+#pragma warning( disable : 4244 )
+#pragma warning( disable : 4305 )
+#endif
+
+
+/* Utility functions */
+
+static void sys_sockerror(char *s)
+{
+#ifdef unix
+ int err = errno;
+#else
+ int err = WSAGetLastError();
+ if (err == 10054) return;
+#endif
+ post("%s: %s (%d)\n", s, strerror(err), err);
+}
+
+
+
+static void sys_closesocket(int fd)
+{
+#ifdef UNIX
+ close(fd); /* shutdown() ?? */
+#endif
+#ifdef NT
+ closesocket(fd);
+#endif
+}
+
+
+/* ------------------------ streamout~ ----------------------------- */
+
+
+static t_class *streamout_class;
+
+typedef struct _streamout
+{
+ t_object x_obj;
+ int x_fd;
+ int x_protocol;
+ t_tag x_tag;
+ t_symbol* hostname;
+ int portno;
+ short* cbuf;
+ int nsamples;
+ int tbufsize;
+} t_streamout;
+
+
+
+static void streamout_tempbuf(t_streamout *x,int size) {
+
+ if (x->cbuf && x->tbufsize) freebytes(x->cbuf,x->tbufsize);
+ x->tbufsize=size;
+ if (!x->cbuf)
+ x->cbuf = getbytes(size*sizeof(short));
+ else
+ x->cbuf = resizebytes(x->cbuf,x->nsamples*sizeof(short),size*sizeof(short));
+ x->nsamples = size;
+}
+
+
+
+static void streamout_disconnect(t_streamout *x)
+{
+ if (x->x_fd >= 0)
+ {
+ sys_closesocket(x->x_fd);
+ x->x_fd = -1;
+ outlet_float(x->x_obj.ob_outlet, 0);
+ }
+}
+
+
+
+static void streamout_connect(t_streamout *x, t_symbol *hostname, t_floatarg fportno)
+{
+ struct sockaddr_in server;
+ struct hostent *hp;
+ int sockfd;
+ int portno = fportno;
+ x->hostname = hostname;
+ x->portno = (int) fportno;
+ x->x_tag.count = 0;
+
+
+ if (x->x_fd >= 0)
+ {
+ post("streamout~: already connected");
+ return;
+ }
+
+ /* create a socket */
+
+ sockfd = socket(AF_INET, x->x_protocol, 0);
+ if (sockfd < 0)
+ {
+ post("streamout: Connection to %s on port %d failed",hostname->s_name,portno);
+ sys_sockerror("socket");
+ return;
+ }
+
+ /* connect socket using hostname provided in command line */
+
+ server.sin_family = AF_INET;
+ hp = gethostbyname(x->hostname->s_name);
+ if (hp == 0)
+ {
+ post("bad host?\n");
+ return;
+ }
+ memcpy((char *)&server.sin_addr, (char *)hp->h_addr, hp->h_length);
+
+ /* assign client port number */
+ server.sin_port = htons((u_short)portno);
+
+ /* try to connect. LATER make a separate thread to do this
+ because it might block */
+ if (connect(sockfd, (struct sockaddr *) &server, sizeof (server)) < 0)
+ {
+ sys_sockerror("connecting stream socket");
+ sys_closesocket(sockfd);
+ return;
+ }
+
+ post("connected host %s on port %d",hostname->s_name, portno);
+
+ x->x_fd = sockfd;
+ outlet_float(x->x_obj.ob_outlet, 1);
+}
+
+
+
+static t_int *streamout_perform(t_int *w)
+{
+ t_streamout* x = (t_streamout*) (w[1]);
+ t_float *in = (t_float *)(w[2]);
+ char* bp;
+ int n = (int)(w[3]);
+ int length = n*SF_SIZEOF(x->x_tag.format);
+ int sent = 0;
+
+ if (n != x->nsamples)
+ streamout_tempbuf(x,n);
+
+ x->x_tag.framesize=length;
+ x->x_tag.count++;
+ /* format the buffer */
+ bp = (char*)in;
+ switch (x->x_tag.format) {
+ case SF_16BIT: {
+ short* cibuf =(short*) x->cbuf;
+ bp = (char*) x->cbuf;
+ while (n--)
+ *cibuf++ = (short) 32767.0 * *in++;
+ break;
+ }
+ case SF_8BIT: {
+ unsigned char* cbuf = (char*) x->cbuf;
+ bp = (char*) x->cbuf;
+ while (n--)
+ *cbuf++ = (unsigned char)(128. * (1.0 + *in++));
+ break;
+ }
+ default:
+ break;
+ }
+
+ if (x->x_fd > 0) {
+ /* send the format tag */
+
+#ifdef unix
+ if (send(x->x_fd,(char*)&x->x_tag,sizeof(t_tag),/*MSG_DONTWAIT|*/MSG_NOSIGNAL) < 0)
+#else
+ if (send(x->x_fd,(char*)&x->x_tag,sizeof(t_tag),0) < 0)
+#endif
+ {
+ sys_sockerror("streamout");
+ streamout_disconnect(x);
+ return (w+4);
+ }
+
+ /* send the buffer */
+
+ for (sent = 0; sent < length;) {
+ int res = 0;
+#ifdef unix
+ res = send(x->x_fd, bp, length-sent, /*MSG_DONTWAIT|*/MSG_NOSIGNAL);
+#else
+ res = send(x->x_fd, bp, length-sent, 0);
+#endif
+ if (res <= 0)
+ {
+ sys_sockerror("streamout");
+ streamout_disconnect(x);
+ break;
+ }
+ else
+ {
+ sent += res;
+ bp += res;
+ }
+ }
+ }
+ return (w+4);
+}
+
+
+
+static void streamout_dsp(t_streamout *x, t_signal **sp)
+{
+ dsp_add(streamout_perform, 3, x, sp[0]->s_vec, sp[0]->s_n);
+}
+
+
+
+static void streamout_format(t_streamout *x,t_symbol* form)
+{
+ if (!strncmp(form->s_name,"float",5))
+ x->x_tag.format = (int) SF_FLOAT;
+
+ if (!strncmp(form->s_name,"16bit",5))
+ x->x_tag.format = (int) SF_16BIT;
+
+ if (!strncmp(form->s_name,"8bit",4))
+ x->x_tag.format = (int) SF_8BIT;
+
+
+ post ("format set to %s", form->s_name);
+}
+
+
+
+static void streamout_host(t_streamout *x,t_symbol* host)
+{
+ if (host != &s_)
+ x->hostname = host;
+
+ if (x->x_fd >= 0) {
+ streamout_connect(x,x->hostname,(float) x->portno);
+ }
+}
+
+
+
+
+static void streamout_float(t_streamout* x,t_float arg)
+{
+ if (arg == 0.0)
+ streamout_disconnect(x);
+ else
+ streamout_connect(x,x->hostname,(float) x->portno);
+}
+
+
+
+static void *streamout_new(t_symbol* prot)
+{
+ t_streamout *x = (t_streamout *)pd_new(streamout_class);
+ outlet_new(&x->x_obj, &s_float);
+
+ x->hostname = gensym("localhost");
+ x->portno = 3000;
+ x->x_fd = -1;
+ x->x_protocol = SOCK_STREAM;
+
+ if (prot != &s_)
+ if (!strncmp(prot->s_name,"udp",3))
+ x->x_protocol = SOCK_DGRAM;
+
+ x->x_tag.format = SF_FLOAT;
+ x->x_tag.channels = 1;
+ x->x_tag.version = 1;
+ x->cbuf = NULL;
+ streamout_tempbuf(x,64);
+ return (x);
+}
+
+
+
+static void streamout_free(t_streamout* x)
+{
+ if (x->cbuf && x->tbufsize) freebytes(x->cbuf,x->tbufsize);
+}
+
+
+
+void streamout_tilde_setup(void)
+{
+ streamout_class = class_new(gensym("streamout~"), (t_newmethod) streamout_new, (t_method) streamout_free,
+ sizeof(t_streamout), 0, A_DEFSYM, 0);
+ class_addmethod(streamout_class, (t_method) streamout_connect,
+ gensym("connect"), A_SYMBOL, A_DEFFLOAT, 0);
+ class_addmethod(streamout_class, (t_method) streamout_disconnect,
+ gensym("disconnect"), 0);
+ class_addfloat(streamout_class,streamout_float);
+ class_addmethod(streamout_class, nullfn, gensym("signal"), 0);
+ class_addmethod(streamout_class, (t_method) streamout_dsp, gensym("dsp"), 0);
+ class_addmethod(streamout_class, (t_method)streamout_format,gensym("format"),A_SYMBOL,0);
+ class_addmethod(streamout_class, (t_method)streamout_host,gensym("host"),A_DEFSYM,0);
+
+}
diff --git a/signal/streamout~.pd b/signal/streamout~.pd
new file mode 100755
index 0000000..56b2ece
--- /dev/null
+++ b/signal/streamout~.pd
@@ -0,0 +1,49 @@
+#N canvas 45 154 820 483 12;
+#X floatatom 227 194 0 0 0;
+#X msg 46 32 disconnect;
+#X obj 368 72 osc~;
+#X floatatom 368 20 0 0 0;
+#X obj 368 44 sig~ 220;
+#X text 13 239 The format message sets the transmission format;
+#X text 11 419 Hopefully we will sometimes have a version where we can compress it for transmission over the "real" net.;
+#X text 14 462 (C) 1999 Guenter Geiger;
+#X obj 455 21 streamin~ 3001;
+#X obj 448 78 dac~;
+#X msg 156 68 connect tritonus 3000;
+#X msg 20 113 format float;
+#X msg 20 144 format 16bit;
+#X text 13 256 format float: send float numbers;
+#X text 12 275 format 16bit: send 16 bit integers;
+#X msg 20 176 format 8bit;
+#X text 380 246 host:;
+#X text 13 219 format:;
+#X obj 227 162 streamout~ localhost 3000;
+#X text 379 193 connect:;
+#X text 378 210 connect sets the host and portnumber and immediatly tries to connect .;
+#X text 380 263 Set the host name and connect to the host \, if a connection was active.;
+#X msg 250 100 1;
+#X msg 284 100 0;
+#X text 379 298 disconnect (0);
+#X text 378 315 disconnect and 0 disconnect the object;
+#X text 379 335 1:;
+#X text 376 352 if the number 1 is sent to streamout \, the object connects to the stored host and portnumber. Default is localhost \, port number 3000;
+#X obj 366 107 *~ 0.01;
+#X msg 179 12 connect gige 15001;
+#X msg 156 37 connect localhost 3001;
+#X text 12 292 format 8bit: send 8 bit integers;
+#X connect 1 0 18 0;
+#X connect 2 0 28 0;
+#X connect 3 0 4 0;
+#X connect 4 0 2 0;
+#X connect 8 0 9 0;
+#X connect 8 0 9 1;
+#X connect 10 0 18 0;
+#X connect 11 0 18 0;
+#X connect 12 0 18 0;
+#X connect 15 0 18 0;
+#X connect 18 0 0 0;
+#X connect 22 0 18 0;
+#X connect 23 0 18 0;
+#X connect 28 0 18 0;
+#X connect 29 0 18 0;
+#X connect 30 0 18 0;