aboutsummaryrefslogtreecommitdiff
path: root/src/z_sfrecord.c
diff options
context:
space:
mode:
authorIOhannes m zmölnig <zmoelnig@users.sourceforge.net>2005-03-22 20:58:25 +0000
committerIOhannes m zmölnig <zmoelnig@users.sourceforge.net>2005-03-22 20:58:25 +0000
commit2b60d55c919e7588f5aff15936e83c300b3660bb (patch)
tree14d860de7f28083d3756ad91b627de70f26788f6 /src/z_sfrecord.c
parentc500bc542cb7cc78d6dac3f7da3bff626056b1aa (diff)
zexy-2.0:
- use of abstractions for objects that allow it - some objects are build both as externals and abstractions (as slower fallbacks) - code-layout is now 1:1 c-file<->object (this should allow for building of zexy as a collection of externals instead as a big library) - matrix-objects have moved to iemmatrix !! svn path=/trunk/externals/zexy/; revision=2641
Diffstat (limited to 'src/z_sfrecord.c')
-rw-r--r--src/z_sfrecord.c592
1 files changed, 0 insertions, 592 deletions
diff --git a/src/z_sfrecord.c b/src/z_sfrecord.c
deleted file mode 100644
index f7eed96..0000000
--- a/src/z_sfrecord.c
+++ /dev/null
@@ -1,592 +0,0 @@
-/*
-sfplay.c - Author: Winfried Ritsch - IEM Graz 10.Mai 99 -
-Modified:
-sfrecord.c - hacked from sfplay ::: 2308:forum::für::umläute:1999 @ iem
-
-please mail problems and ideas for improvements to
-ritsch@iem.kug.ac.at
-zmoelnig@iem.kug.ac.at
-*/
-
-/* to do :: add headers for wav, aiff etc files */
-
-
-/* #define DEBUG_ME // for debugging messages */
-
-#include "zexy.h"
-
-
-/* #include "m_imp.h" */
-
-#define DACBLKSIZE 64 /* in m_imp.h, but error if it is included it here*/
-
-#ifdef NT
-#pragma warning( disable : 4244 )
-#pragma warning( disable : 4305 )
-#endif
-
-#include <stdio.h>
-#include <string.h>
-#include <fcntl.h>
-
-/* ------------------------ sfrecord ----------------------------- */
-#define MAX_CHANS 8 /* channels for soundfiles 1,2,4,8 */
-
-#ifdef NT
-#define BINWRITEMODE "wb"
-#endif
-#ifdef unix
-#include <unistd.h>
-#include <sys/mman.h>
-#define BINWRITEMODE "w"
-#endif
-
-static t_class *sfrecord_class;
-
-typedef struct _sfrecord
-{
- t_object x_obj;
-
- void* filep; /* pointer to file data read in mem */
- t_symbol* filename; /* filename */
-
- /*
- because there is no command queue,
- flags are used instead
- */
- t_int write; /* write: 1, stop: 0 */
- t_int please_stop; /* can be reset only by stop-state itself */
- t_int please_close; /* can be reset only by close-state */
- t_int x_channels; /* channels to write */
- t_float x_offset; /* offset to start writing */
- t_float offset; /* inlet value offset in secs */
- t_float x_skip; /* skip bytes because header */
- t_int skip; /* pending skip if 1 */
- t_float x_speed; /* write speed, not supported in this version */
- t_int size; /* size of file (if memory mapped) */
- t_int swap; /* swap bytes from l->b or b->m */
- FILE *fp; /* file oper non-NULL of open */
- t_int state; /* which state is writer in */
- t_int count; /* count for ticks before next step */
-
-} t_sfrecord;
-
-/* states of statemachine */
-#define SFRECORD_WAIT 0 /* wait for open */
-#define SFRECORD_OPEN 1
-#define SFRECORD_CLOSE 2
-#define SFRECORD_SKIP 3
-#define SFRECORD_WRITE 4
-#define SFRECORD_STOP 5
-#define SFRECORD_ERROR -1
-
-#define SFRECORD_WAITTICKS 10 /* 1 tick of 64 Samples is ca.1.5ms on 441000 */
-
-/* split the os-calls in as many steps as possible
-to split them on different ticks in steps of SFRECORD_WAITTICKS
-to avoid peak performance */
-
-/* like the one from garray */
-static int sfrecord_am_i_big_endian()
-{
- unsigned short s = 1;
- unsigned char c = *(char *) (&s);
-#ifdef DEBUG_ME
- post("i am %s-endian", c?"little":"big");
-#endif
- return(c==0);
-}
-
-static void state_out(t_sfrecord *x, int state)
-{ /* outlet the actual state */
- outlet_float(x->x_obj.ob_outlet, state);
-}
-
-
-/* METHOD: "open" file */
-
-/* this dont use memory map, because I dont know about this on NT ?
-Use of the buffered functions fopen, fseek fread fclose instead the
-non buffered ones open read close */
-
-void sfrecord_open(t_sfrecord *x,t_symbol *filename,t_symbol *endian)
-{
-
- if(x->state != SFRECORD_WAIT)
- {
- post("sfrecord: first close %s before open %s",x->filename->s_name,filename->s_name);
- return;
- }
-
-/* test if big endian else asume little endian
- should be 'l' but could be anything*/
-
- if(sfrecord_am_i_big_endian())
- x->swap = !(endian->s_name[0] == 'b');
- else
- x->swap = (endian->s_name[0] == 'b');
-
-// x->skip = 1; /* skip header after open;; sometimes we´ll have to write a header using the x->skip; so don´t delete it completely*/
-
- x->filename = filename;
-
-#ifdef DEBUG_ME
- post("sfrecord: opening %s",x->filename->s_name);
-#endif
-
- if (x->fp != NULL)fclose(x->fp); /* should not happen */
-
- if (!(x->fp = fopen(x->filename->s_name,BINWRITEMODE)))
- {
- error("sfrecord: can't open %s", x->filename->s_name);
- }
-}
-
-
-
-/* METHOD: close */
-static void sfrecord_close(t_sfrecord *x)
-{
- x->write = 0;
- x->please_close = 1;
-
- /* now in state machine
- if(x->fp != NULL)
- {
- fclose(x->fp);
- x->fp = NULL;
- }
- */
-
-#ifdef DEBUG_ME
- post("sfrecord: closing ");
-#endif
- return;
-}
-
-/* for skipping header of soundfile Don´t use this for memory map */
-
-static int sfrecord_skip(t_sfrecord *x)
-{
- if(!x->skip) return 0;
-
-#ifdef DEBUG_ME
- post("sfrecord:skip to %f",x->x_skip);
-#endif
-
- x->skip = 0;
- return 1;
-}
-
-/* Input, method for Start stop */
-
-static void sfrecord_start(t_sfrecord *x)
-{
-#ifdef DEBUG_ME
- post("sfrecord: start at %d", x->x_offset);
-#endif
-
- state_out(x, 1);
- x->write=1;
-}
-
-static void sfrecord_stop(t_sfrecord *x)
-{
-#ifdef DEBUG_ME
- post("sfrecord: stop");
-#endif
- state_out(x, 0);
-
- x->write=0;
- x->please_stop = 1;
-}
-
-static void sfrecord_float(t_sfrecord *x, t_floatarg f)
-{
- int t = f;
- if (t) sfrecord_start(x);
- else sfrecord_stop(x);
-}
-
-/* say what state we´re in */
-void sfrecord_bang(t_sfrecord* x)
-{
- if (x->state == SFRECORD_WRITE) state_out(x, 1); else state_out(x, 0);
-}
-
-/* ******************************************************************************** */
-/* the work krow eht */
-/* ******************************************************************************** */
-
-
-static t_int *sfrecord_perform(t_int *w)
-{
- t_sfrecord* x = (t_sfrecord*)(w[1]);
- short* buf = x->filep;
- short* bufstart = buf;
- int c = x->x_channels;
-
- int i,j,n, s_n;
- t_float* in[MAX_CHANS];
-
- short s;
- int swap = x->swap;
-
- for (i=0;i<c;i++)
- in[i] = (t_float *)(w[2+i]);
-
- n = s_n = (int)(w[2+c]);
-
- /* loop */
-
- switch(x->state){
-
- /* just wait */
- case SFRECORD_WAIT:
-
- if(x->fp != NULL){
-#ifdef DEBUG_ME
- post("wait -> open");
-#endif
- x->state = SFRECORD_OPEN;
- x->count = SFRECORD_WAITTICKS;
- };
- break;
-
- /* if in open state, already opened but wait for skip */
- case SFRECORD_OPEN: /* file has opened wait some time */
-
- if(!(x->count--)){
-#ifdef DEBUG_ME
- post("open -> skip");
-#endif
- x->state = SFRECORD_SKIP;
- x->count = SFRECORD_WAITTICKS;
- };
-
- break;
-
- /* in skipmode wait until ready for stop */
- case SFRECORD_SKIP:
-
- if(x->count == SFRECORD_WAITTICKS)
- {
- if(!x->fp)
- {
- x->state = SFRECORD_CLOSE;
- x->count=1;
-#ifdef DEBUG_ME
- post("skip -> close");
-#endif
- break;
- }
- sfrecord_skip(x);
- }
- if(!(x->count--))
- {
-#ifdef DEBUG_ME
- post("skip -> stop");
-#endif
- x->state = SFRECORD_STOP;
- x->count = SFRECORD_WAITTICKS;
- };
- break;
-
- case SFRECORD_STOP: /* in stop state mainly waits for write */
-
- x->please_stop = 0;
-
- if(x->please_close)
- {
- x->state = SFRECORD_CLOSE;
- x->count = SFRECORD_WAITTICKS;
-#ifdef DEBUG_ME
- post("stop -> close");
-#endif
- }
- else if(x->skip)
- {
- x->state = SFRECORD_SKIP;
- x->count = SFRECORD_WAITTICKS;
-
-#ifdef DEBUG_ME
- post("stop -> skip");
-#endif
-
- }
- else if(x->write)
- {
-
-#ifdef DEBUG_ME
- post("stop -> write");
-#endif
- x->state = SFRECORD_WRITE;
- state_out(x, 1);
- }
- break;
-
- case SFRECORD_WRITE: /* yes write now */
-
- if(!x->write || x->please_stop)
- {
- /* if closing dont need to go to stop */
- if(x->please_close) {
- x->state = SFRECORD_CLOSE;
- x->count = SFRECORD_WAITTICKS;
-#ifdef DEBUG_ME
- post("write -> close");
-#endif
- state_out(x, 0);
-
- }
- else {
- x->state = SFRECORD_STOP;
-#ifdef DEBUG_ME
- post("write -> stop");
-#endif
- };
- break;
- }
-
- /* should never happen */
- if(!x->filep){
- x->state = SFRECORD_ERROR;
- error("sfrecord: writing but no buffer ???? write");
- return (w+4+c);
- }
-
- /* copy float to 16 Bit and swap if neccesairy */ /* LATER treat overflows */
- while (n--) {
- for (i=0;i<c;i++) {
- s = *in[i]++ * 32768.;
- if (swap) s = ((s & 0xFF)<< 8) | ((s& 0xFF00) >> 8);
- *buf++ = s;
- }
- }
-
- /* then write soundfile 16 bit*/
- if ( (j = fwrite(bufstart, sizeof(short), c*s_n, x->fp)) < 1) {
- x->state = SFRECORD_ERROR;
- x->count = SFRECORD_WAITTICKS;
-#ifdef DEBUG_ME
- post("write -> write error\t %xd\t%xd\t%d\t%d", x->filep, buf, c*s_n*sizeof(short), j);
-#endif
- break;
- }
-
-#if 0
- if((j=fwrite(buf,sizeof(short),c*n,x->fp)) < (unsigned int) n)
- {
- if(feof(x->fp)){
-
- while (n--) {
- for (i=0;i<c;i++) {
- if(--j > 0){
- s = *buf++;
- if(swap) s = ((s & 0xFF)<< 8) | ((s& 0xFF00) >> 8);
- *out[i]++ = s*(1./32768.);
- }
- else
- *out[i]++ = 0;
- }
- }
- }
-
- x->state = SFRECORD_STOP;
- x->write = 0;
- return(w+c+3);
- }
- /* or error if(ferror()) */
- x->state = SFRECORD_ERROR;
- x->count = SFRECORD_WAITTICKS;
-#ifdef DEBUG_ME
- post("write -> write error");
-#endif
- break;
- };
-#endif //0
- return (w+c+3); /* writing was fine */
-
-
- /* ok :?: write error, please close */
- case SFRECORD_ERROR:
-
- if(!(x->count--)) {
- x->state = SFRECORD_CLOSE;
- sfrecord_close(x);
-#ifdef DEBUG_ME
- post("sfrecord error writing sf: error -> close");
-#endif
- x->count = SFRECORD_WAITTICKS;
- }
- break;
-
- /* in close state go to wait afterwards */
- case SFRECORD_CLOSE:
-
- x->please_close = 0;
-
- /* wait until ready for close operation */
- if(!(x->count--)){
-
- x->state = SFRECORD_WAIT;
- x->count = SFRECORD_WAITTICKS;
-
- /* avoid openfiles */
- if(x->fp){fclose(x->fp);x->fp = NULL;};
-
-#ifdef DEBUG_ME
- post("sfrecord: close -> wait");
-#endif
- }
- break;
-
- }; /*case */
-
- return(w+c+3);
-}
-
-
-
-
-/* ---------------------- Setup junk -------------------------- */
-
-static void sfrecord_dsp(t_sfrecord *x, t_signal **sp)
-{
-
-#ifdef DEBUG_ME
- post("sfrecord: dsp");
- post("offset = %f\tspeed = %f\t", x->offset, x->x_speed);
-#endif
-
-
- switch (x->x_channels) {
- case 1:
- dsp_add(sfrecord_perform, 3, x,
- sp[0]->s_vec, /* in 1 */
- sp[0]->s_n);
- break;
- case 2:
- dsp_add(sfrecord_perform, 4, x,
- sp[0]->s_vec,
- sp[1]->s_vec,
- sp[0]->s_n);
- break;
- case 4:
- dsp_add(sfrecord_perform, 6, x,
- sp[0]->s_vec,
- sp[1]->s_vec,
- sp[2]->s_vec,
- sp[3]->s_vec,
- sp[0]->s_n);
- break;
- case 8:
- dsp_add(sfrecord_perform, 9, x,
- sp[0]->s_vec,
- sp[1]->s_vec,
- sp[2]->s_vec,
- sp[3]->s_vec,
- sp[4]->s_vec,
- sp[5]->s_vec,
- sp[6]->s_vec,
- sp[7]->s_vec,
- sp[0]->s_n);
- break;
- }
-}
-
-
-/* create sfrecord with args <channels> <skip> */
-static void *sfrecord_new(t_floatarg chan)
-{
- t_sfrecord *x = (t_sfrecord *)pd_new(sfrecord_class);
- t_int c = chan;
-
- switch(c){
- /* ok */
- case 1: case 2: case 4: case 8: break;
- /* try it, good luck ... */
- case 3: c = 2; break;
- case 5: case 6: case 7: c=7; break;
- default: c=1; break;
- }
-
- outlet_new(&x->x_obj, &s_float);
-
- x->x_channels = c;
- x->x_skip = x->x_offset = 0;
- x->skip = 1;
- x->offset = 0.;
- x->x_speed = 1.0;
- x->write = 0;
- x->please_stop = 0;
- x->please_close = 0;
- x->state = SFRECORD_WAIT;
- x->count = 0;
- x->filename = NULL;
- x->fp = NULL;
- x->swap = 1;
-
- c--;
-
- while (c--) {
-#ifdef DEBUG_ME
- post("create extra channel #%d", c);
-#endif
- inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); /* channels inlet */
- }
-
- x->filep = t_getbytes(DACBLKSIZE*sizeof(short)*x->x_channels);
-
-#ifdef DEBUG_ME
- post("get_bytes DACBLKSIZE*%d*%d->%ld",sizeof(short),x->x_channels,x->filep);
- post("sfrecord: x_channels = %d, x_speed = %f, x_skip = %f",x->x_channels,x->x_speed,x->x_skip);
-#endif
-
- return (x);
-}
-
-
-static void helper(void)
-{
- post("\nsfplay :: a raw-data soundfile-recorder");
- post("\ncreation :: sfrecord <channels>\t: channels set the number of channels");
- post("\nopen [<path>]<filename> [<endianity>]\t:: open b(ig) or l(ittle) endian file"
- "\nclose\t\t\t:: close file (aka eject)"
- "\nstart\t\t\t:: start playing"
- "\nstop\t\t\t:: stop playing"
- "\nbang\t\t\t:: outputs the current state (1_recording, 0_not-recording)");
-
- post("\n\nyou can also start recording with a ´1´, and stop with a ´0´");
-}
-
-
-static void sfrecord_free(t_sfrecord *x)
-{
- freebytes(x->filep, DACBLKSIZE*sizeof(short)*x->x_channels);
-}
-
-void z_sfrecord_setup(void)
-{
- sfrecord_class = class_new(gensym("sfrecord"), (t_newmethod)sfrecord_new, (t_method)sfrecord_free,
- sizeof(t_sfrecord), 0, A_DEFFLOAT, A_DEFFLOAT,0);
- class_addmethod(sfrecord_class, nullfn, gensym("signal"), 0);
- class_addmethod(sfrecord_class, (t_method)sfrecord_dsp, gensym("dsp"), 0);
-
- /* method open with filename */
- class_addmethod(sfrecord_class, (t_method)sfrecord_open, gensym("open"), A_SYMBOL,A_SYMBOL,A_NULL);
- class_addmethod(sfrecord_class, (t_method)sfrecord_close, gensym("close"), A_NULL);
-
- class_addmethod(sfrecord_class, (t_method)sfrecord_start, gensym("start"), A_NULL);
- class_addmethod(sfrecord_class, (t_method)sfrecord_stop, gensym("stop"), A_NULL);
-
- /* start/stop with 0/1 */
- class_addfloat(sfrecord_class, sfrecord_float);
-
- /* bang out the current-state to the outlet*/
- class_addbang(sfrecord_class,sfrecord_bang);
-
- /* some help */
- class_addmethod(sfrecord_class, (t_method)helper, gensym("help"), A_NULL);
- class_sethelpsymbol(sfrecord_class, gensym("zexy/sf-play_record"));
-}