diff options
author | dieter kovacic <d13@users.sourceforge.net> | 2002-08-26 12:28:11 +0000 |
---|---|---|
committer | dieter kovacic <d13@users.sourceforge.net> | 2002-08-26 12:28:11 +0000 |
commit | 42da6c0e09798775a1e660eb63967af03e0bde3c (patch) | |
tree | 0c67ed12957ff343db94516b8fd1fb9f0699ac1e | |
parent | f79b786e8b158bea4a9f73b35d59c2e531ee8c50 (diff) |
added sfwrite13~.c
svn path=/trunk/externals/ext13/; revision=90
-rw-r--r-- | sfwrite13~.c | 309 |
1 files changed, 309 insertions, 0 deletions
diff --git a/sfwrite13~.c b/sfwrite13~.c new file mode 100644 index 0000000..cec3a09 --- /dev/null +++ b/sfwrite13~.c @@ -0,0 +1,309 @@ +/* original source (sfwrite~.c) by Guenter Geiger <geiger@epy.co.at> */
+/* added buffering for write-actions to reduce disc-activity <dieb13 at klingt.org>*/
+
+
+#include "m_imp.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_TRUNC
+#endif
+#define MAX_CHANS 4
+
+
+/*
+ * ------------------------------------------- sfwrite13~ -------------------------------
+ */
+
+#define BLOCKTIME 0.01
+#define uint32 unsigned int
+#define uint16 unsigned short
+
+static t_class *sfwrite13_class;
+
+typedef struct _sfwrite13
+{
+ t_object x_obj;
+ t_symbol* filename;
+ int x_file;
+ int do_close;
+ short* cbuf;
+ short* cbufptr;
+ uint32 bufsize;
+ t_int rec;
+ t_int x_channels;
+ uint32 size;
+ t_glist * x_glist;
+ t_int x_blocked;
+ t_int x_blockwarn;
+} t_sfwrite13;
+
+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 sfwrite13_tempbuf(t_sfwrite13 *x,int size)
+{
+ post("channels:%d",x->x_channels);
+ if (!x->cbuf){
+ x->cbuf = getbytes(x->x_channels * size*sizeof(short));
+ x->bufsize = size;
+ }else{
+ x->cbuf = resizebytes(x->cbuf,x->bufsize * x->x_channels * sizeof(short), x->x_channels * size * sizeof(short));
+ x->bufsize = size;
+ }
+ x->cbufptr = x->cbuf;
+}
+
+static void sfwrite13_wave_setup(t_sfwrite13* 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 sfwrite13_dowrite(t_sfwrite13 *x)
+{
+ double timebefore,timeafter,late;
+ int ret;
+
+ timebefore = sys_getrealtime();
+ if ((ret =write(x->x_file,x->cbuf,sizeof(short)*(x->cbufptr - x->cbuf))) < (signed int)sizeof(short)*(x->cbufptr - x->cbuf)) {
+ post("sfwrite13: short write %d",ret);
+ }
+ timeafter = sys_getrealtime();
+ late = timeafter - timebefore;
+
+ if (late > BLOCKTIME && x->x_blockwarn) {
+ post("sfwrite13 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 += ret ;
+ x->cbufptr = x->cbuf;
+
+}
+
+static void sfwrite13_close(t_sfwrite13 *x)
+{
+ if (x->x_file > 0) {
+ t_wave w;
+ sfwrite13_dowrite(x);
+ sfwrite13_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 sfwrite13_open(t_sfwrite13 *x,t_symbol *filename)
+{
+ char fname[MAXPDSTRING];
+
+ if (filename == &s_) {
+ post("sfwrite13: open without filename");
+ return;
+ }
+
+ canvas_makefilename(glist_getcanvas(x->x_glist), filename->s_name,
+ fname, MAXPDSTRING);
+
+ x->x_blocked = 0;
+ x->filename = filename;
+ post("sfwrite13: filename = %s",x->filename->s_name);
+
+ sfwrite13_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;
+ x->do_close=0;
+
+
+}
+
+static void sfwrite13_block(t_sfwrite13 *x, t_floatarg f)
+{
+ x->x_blockwarn = f;
+}
+
+
+static void sfwrite13_float(t_sfwrite13 *x, t_floatarg f)
+{
+ int t = f;
+ if (t) {
+ post("sfwrite13: start", f);
+ x->rec=1;
+ }
+ else {
+ post("sfwrite13: stop", f);
+ x->rec=0;
+ x->do_close = 1;
+ }
+
+}
+
+
+
+static t_int *sfwrite13_perform(t_int *w)
+{
+ t_sfwrite13* x = (t_sfwrite13*)(w[1]);
+ t_float * in[4];
+ int c = x->x_channels;
+ int i,num,n;
+
+ for (i=0;i < c;i++) {
+ in[i] = (t_float *)(w[2+i]);
+ }
+
+ n = num = (int)(w[2+c]);
+
+ if (x->rec && x->x_file) {
+ while (n--) {
+ for (i=0;i<c;i++) {
+ *x->cbufptr++ = (short)(*(in[i])++ * 32768.);
+ }
+ if ((x->cbufptr - x->cbuf) > (x->bufsize )) {sfwrite13_dowrite(x);}
+ }
+ }
+
+ if (x->do_close) {
+ sfwrite13_close(x);
+ }
+
+ return (w+3+c);
+}
+
+
+
+static void sfwrite13_dsp(t_sfwrite13 *x, t_signal **sp)
+{
+ switch (x->x_channels) {
+ case 1:
+ dsp_add(sfwrite13_perform, 3, x, sp[0]->s_vec,
+ sp[0]->s_n);
+ break;
+ case 2:
+ dsp_add(sfwrite13_perform, 4, x, sp[0]->s_vec,
+ sp[1]->s_vec, sp[0]->s_n);
+ break;
+ case 4:
+ dsp_add(sfwrite13_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 sfwrite13_free(t_sfwrite13* x)
+{
+ sfwrite13_close(x);
+}
+
+
+static void *sfwrite13_new(t_floatarg chan)
+{
+ t_sfwrite13 *x = (t_sfwrite13 *)pd_new(sfwrite13_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);
+ }
+ sfwrite13_tempbuf(x,8192);
+ return (x);
+}
+
+static void *sfwrite13_buffersize(t_sfwrite13 *x,t_floatarg s){
+ sfwrite13_tempbuf(x,(int)s);
+}
+
+void sfwrite13_setup(void)
+{
+ sfwrite13_class = class_new(gensym("sfwrite13~"), (t_newmethod)sfwrite13_new, (t_method)sfwrite13_free,
+ sizeof(t_sfwrite13), 0,A_DEFFLOAT,0);
+ class_addmethod(sfwrite13_class,nullfn,gensym("signal"), 0);
+ class_addmethod(sfwrite13_class, (t_method) sfwrite13_dsp, gensym("dsp"), 0);
+ class_addmethod(sfwrite13_class, (t_method) sfwrite13_open, gensym("open"), A_SYMBOL,A_NULL);
+ class_addmethod(sfwrite13_class, (t_method) sfwrite13_close, gensym("close"), 0);
+ class_addmethod(sfwrite13_class, (t_method) sfwrite13_block,gensym("block"),A_DEFFLOAT,0);
+ class_addmethod(sfwrite13_class, (t_method) sfwrite13_buffersize,gensym("buffersize"),A_DEFFLOAT,0);
+ class_addfloat(sfwrite13_class, sfwrite13_float);
+
+}
+
+
+
+
+
+
+
+
|