From fc3d3c0a4f110a23335398c327ac0a4fc949d5cb Mon Sep 17 00:00:00 2001 From: Guenter Geiger Date: Mon, 17 Jun 2002 10:13:57 +0000 Subject: This commit was generated by cvs2svn to compensate for changes in r12, which included commits to RCS files with non-trunk default branches. svn path=/trunk/externals/ggee/; revision=13 --- signal/Makefile | 51 +++++++ signal/apply~.c | 151 +++++++++++++++++++ signal/apply~.pd | 19 +++ signal/atan2~.c | 86 +++++++++++ signal/atan2~.pd | 4 + signal/mixer~.c | 107 ++++++++++++++ signal/mixer~.pd | 87 +++++++++++ signal/pipewrite~.c | 216 +++++++++++++++++++++++++++ signal/rtin~.c | 76 ++++++++++ signal/rtin~.pd | 32 ++++ signal/sfread~.c | 317 ++++++++++++++++++++++++++++++++++++++++ signal/sfread~.pd | 44 ++++++ signal/sfwrite.pd | 45 ++++++ signal/sfwrite~.c | 284 ++++++++++++++++++++++++++++++++++++ signal/stream.h | 30 ++++ signal/streamin~.c | 404 +++++++++++++++++++++++++++++++++++++++++++++++++++ signal/streamin~.pd | 41 ++++++ signal/streamout~.c | 323 ++++++++++++++++++++++++++++++++++++++++ signal/streamout~.pd | 49 +++++++ 19 files changed, 2366 insertions(+) create mode 100755 signal/Makefile create mode 100644 signal/apply~.c create mode 100644 signal/apply~.pd create mode 100755 signal/atan2~.c create mode 100755 signal/atan2~.pd create mode 100755 signal/mixer~.c create mode 100755 signal/mixer~.pd create mode 100755 signal/pipewrite~.c create mode 100755 signal/rtin~.c create mode 100755 signal/rtin~.pd create mode 100755 signal/sfread~.c create mode 100755 signal/sfread~.pd create mode 100755 signal/sfwrite.pd create mode 100755 signal/sfwrite~.c create mode 100755 signal/stream.h create mode 100755 signal/streamin~.c create mode 100755 signal/streamin~.pd create mode 100755 signal/streamout~.c create mode 100755 signal/streamout~.pd (limited to 'signal') 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 */ + + +#include "math.h" +#include + +/* ----------------------------- 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;is_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;ix_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 */ + + + +#include "math.h" +#include + +/* ----------------------------- 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 */ + + +#include "math.h" +#include + +/* ----------------------------- 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;ix_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;jx_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 */ + + +#include "m_imp.h" +//#include +#include "g_canvas.h" +#ifdef NT +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif + +#include +#include +#include +#include +#include +#include +#include + +/* + * -------------------------- 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 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 */ + + + #include + #include + #include + #include + #include + +// int gettimeofday(struct timeval *tv, struct timezone *tz); + + + +#include "math.h" +#include + + +/* ----------------------------- 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 */ + + +#include +/*#include */ +#include "g_canvas.h" +#ifdef NT +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif + +#include +#include +#ifndef NT +#include +#include +#else +#include +#endif + + +#include +#include + +/* ------------------------ 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 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>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>1)<<1; + while (n--) { + for (i=0;i end) { + if (x->x_loop) aoff = x->x_skip; + else break; + } + } + + /* Fill with zero in case of end */ + n++; + while (n--) + for (i=0;ix_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 ; +#X text 276 35 start position in samples (defaults to ); +#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 */ + + +#include +/*#include */ +#include "g_canvas.h" +#ifdef NT +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif + +#include +#include +#ifndef NT +#include +#include +#else +#include +#endif +#include +#include + + +#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;ix_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 \"",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 (C) 1999 */ + +#include +#include "stream.h" + +#include +#include +#ifdef unix +#include +#include +#include +#include +#include +#include +#include +#include +#define SOCKET_ERROR -1 +#else +#include +#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;iaverage[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;iaverage[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;iframes[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 */ + +#include +#include "stream.h" + +#include +#include +#include +#ifdef unix +#include +#include +#include +#include +#define SOCKET_ERROR -1 +#else +#include +#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; -- cgit v1.2.1