This is io.c in view mode; [Download] [Up]
#include <math.h> #include <stdio.h> #include <fcntl.h> /* the following procedures are used to allocate and manage the IO buffers and huge delay lines */ /* used in io.lisp and mus.lisp -- Lisp's garbage collector is not being very smart about these guys */ /* compiled cc io.c -c -O */ /* foreign function tie into clm is in c-io.lisp */ /* all data reads in clm go through clm_read and clm_write */ /* file opens are clm_open_read, clm_reopen_write, and clm_open_write */ #ifdef __LITTLE_ENDIAN__ #include <architecture/byte_order.h> #include <sound/utilsound.h> int clm_write(int fd, char *buf, int n) { int bytes; /* SNDSwapHostToSound(buf,buf,(n>>1),1,3); */ char *i,*j; char k; int nn; for (i=buf,j=(buf+1),nn=0;nn<n;nn+=2,i+=2,j+=2) { k=*j; *j = *i; *i = k; } bytes = write(fd,buf,n); return(bytes); } short clm_short(short n) {return(NXSwapShort(n));} int clm_int(int n) {return(NXSwapInt(n));} #else int clm_write(int fd, char *buf, int n) {return(write(fd,buf,n));} short clm_short(short n) {return(n);} int clm_int(int n) {return(n);} #endif /* for arbitrary sound data formats, we need clm_read, clm_seek as though they were 16-bit */ /* That is, lisp thinks all the data is 16-bit linear, but we provide read translations at the lowest level */ #include "sound_types.h" /* open might not return a small integer */ #define FILE_DESCRIPTORS 128 #define BASE_FILE_DESCRIPTORS 64 static int clm_datum_format[FILE_DESCRIPTORS]; static int clm_datum_size[FILE_DESCRIPTORS]; static int clm_datum_location[FILE_DESCRIPTORS]; static int clm_files_ready = 0; static int clm_files[BASE_FILE_DESCRIPTORS]; int convert_fd(int n) { if (n<BASE_FILE_DESCRIPTORS) return(n); else { int i; for (i=0;i<BASE_FILE_DESCRIPTORS;i++) { if (clm_files[i] == n) return(i+BASE_FILE_DESCRIPTORS); } return(-1); } } int open_clm_file (int tfd) { int fd; if (tfd < BASE_FILE_DESCRIPTORS) return(tfd); if (clm_files_ready == 0) { for (fd=0;fd<BASE_FILE_DESCRIPTORS;fd++) clm_files[fd]=-1; clm_files_ready = 1; } for (fd=0;fd<BASE_FILE_DESCRIPTORS;fd++) { if (clm_files[fd] == -1) { clm_files[fd] = tfd; return(fd+BASE_FILE_DESCRIPTORS); } } return(-1); } void open_clm_file_descriptors (int tfd, int df, int ds, int dl) { /* transfers header info from functions in header.c back to us for reads here, in fft.c, and in merge.c */ int fd; fd = open_clm_file(tfd); clm_datum_format[fd] = df; clm_datum_size[fd] = ds; clm_datum_location[fd] = dl; } void close_clm_file_descriptors(int tfd) { int fd; fd = convert_fd(tfd); if (fd >= BASE_FILE_DESCRIPTORS) clm_files[fd-BASE_FILE_DESCRIPTORS] = -1; } long clm_seek(int tfd, long offset, int origin) { int fd,siz; fd = convert_fd(tfd); siz = clm_datum_size[fd]; if ((siz == 2) || (origin != 0)) return(lseek(fd,offset,origin)); else { int loc,true_loc,header_end; header_end = clm_datum_location[fd]; loc = offset - header_end; switch (siz) { case 1: true_loc = lseek(fd,header_end+(loc>>1),origin); /* now pretend we're still in 16-bit land and return where we "actually" are in that region */ /* that is, loc (in bytes) = how many (2-byte) samples into the file we want to go, return what we got */ return(header_end + ((true_loc - header_end)<<1)); break; case 3: true_loc = lseek(fd,header_end+loc+(loc>>1),origin); return(true_loc + ((true_loc - header_end)>>1)); break; case 4: true_loc = lseek(fd,header_end+(loc<<1),origin); return(header_end + ((true_loc - header_end)>>1)); break; case 8: true_loc = lseek(fd,header_end+(loc<<2),origin); return(header_end + ((true_loc - header_end)>>2)); break; } } } /* generated by SNDiMulaw on a NeXT -- see /usr/include/sound/mulaw.h */ static const short mulaw[256] = { -32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956, -23932, -22908, -21884, -20860, -19836, -18812, -17788, -16764, -15996, -15484, -14972, -14460, -13948, -13436, -12924, -12412, -11900, -11388, -10876, -10364, -9852, -9340, -8828, -8316, -7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140, -5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092, -3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004, -2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980, -1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436, -1372, -1308, -1244, -1180, -1116, -1052, -988, -924, -876, -844, -812, -780, -748, -716, -684, -652, -620, -588, -556, -524, -492, -460, -428, -396, -372, -356, -340, -324, -308, -292, -276, -260, -244, -228, -212, -196, -180, -164, -148, -132, -120, -112, -104, -96, -88, -80, -72, -64, -56, -48, -40, -32, -24, -16, -8, 0, 32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956, 23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764, 15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412, 11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316, 7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140, 5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092, 3900, 3772, 3644, 3516, 3388, 3260, 3132, 3004, 2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980, 1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436, 1372, 1308, 1244, 1180, 1116, 1052, 988, 924, 876, 844, 812, 780, 748, 716, 684, 652, 620, 588, 556, 524, 492, 460, 428, 396, 372, 356, 340, 324, 308, 292, 276, 260, 244, 228, 212, 196, 180, 164, 148, 132, 120, 112, 104, 96, 88, 80, 72, 64, 56, 48, 40, 32, 24, 16, 8, 0}; /* generated from toast_alaw.c */ static const short alaw[256] = { 5120, -5376, 320, -336, 20480, -21504, 1280, -1344, 2560, -2688, 64, -80, 10240, -10752, 640, -672, 7168, -7424, 448, -464, 28672, -29696, 1792, -1856, 3584, -3712, 192, -208, 14336, -14848, 896, -928, 4096, -4352, 256, -272, 16384, -17408, 1024, -1088, 2048, -2176, 0, -16, 8192, -8704, 512, -544, 6144, -6400, 384, -400, 24576, -25600, 1536, -1600, 3072, -3200, 128, -144, 12288, -12800, 768, -800, 5632, -5888, 352, -368, 22528, -23552, 1408, -1472, 2816, -2944, 96, -112, 11264, -11776, 704, -736, 7680, -7936, 480, -496, 30720, -31744, 1920, -1984, 3840, -3968, 224, -240, 15360, -15872, 960, -992, 4608, -4864, 288, -304, 18432, -19456, 1152, -1216, 2304, -2432, 32, -48, 9216, -9728, 576, -608, 6656, -6912, 416, -432, 26624, -27648, 1664, -1728, 3328, -3456, 160, -176, 13312, -13824, 832, -864, 5376, -5632, 336, -352, 21504, -22528, 1344, -1408, 2688, -2816, 80, -96, 10752, -11264, 672, -704, 7424, -7680, 464, -480, 29696, -30720, 1856, -1920, 3712, -3840, 208, -224, 14848, -15360, 928, -960, 4352, -4608, 272, -288, 17408, -18432, 1088, -1152, 2176, -2304, 16, -32, 8704, -9216, 544, -576, 6400, -6656, 400, -416, 25600, -26624, 1600, -1664, 3200, -3328, 144, -160, 12800, -13312, 800, -832, 5888, -6144, 368, -384, 23552, -24576, 1472, -1536, 2944, -3072, 112, -128, 11776, -12288, 736, -768, 7936, -8192, 496, -512, 31744, -32768, 1984, -2048, 3968, -4096, 240, -256, 15872, -16384, 992, -1024, 4864, -5120, 304, -320, 19456, -20480, 1216, -1280, 2432, -2560, 48, -64, 9728, -10240, 608, -640, 6912, -7168, 432, -448, 27648, -28672, 1728, -1792, 3456, -3584, 176, -192, 13824, -14336, 864, -896}; #define CONVERT_BUF_SIZE 4096 static unsigned char convert_buf[CONVERT_BUF_SIZE]; int clm_read(int tfd, char *buf, long nbytes) { /* read nbytes bytes into buf -- as though data was 16-bit linear -- include any needed conversions */ int fd; fd = convert_fd(tfd); if (clm_datum_format[fd] == snd_16_linear) { #ifdef __LITTLE_ENDIAN__ /* * this is just a temporary stop-gap. We need to figure out what the relation is between * the current processor and the data in the sound file and swap whenever that is indicated. * This also affects the read loops below for non-8 bit data. */ int bytes; bytes = read(fd,buf,nbytes); /* SNDSwapSoundToHost(buf,buf,(bytes>>1),1,3); */ /* This is causing clicks */ { char *i,*j; char k; int nn; for (i=buf,j=(buf+1),nn=0;nn<bytes;nn+=2,i+=2,j+=2) { k = *j; *j = *i; *i = k; } } return(bytes); #else return(read(fd,buf,nbytes)); #endif } else { /* read in a buffer's worth, write to buf while converting */ int bytes,i,j,k,n,total,lim,siz; short *m; unsigned char *jchar; float *jfloat; char *jbyte; long *jword; double *jdouble; siz = clm_datum_size[fd]; switch (siz) { case 1: bytes = (nbytes>>1); break; case 2: bytes = nbytes; break; case 3: bytes = (nbytes+(nbytes>>1)); break; case 4: bytes = (nbytes<<1); break; case 8: bytes = (nbytes<<2); break; } total=0; for (i=0;i<bytes;i+=CONVERT_BUF_SIZE) { k=bytes-i; if (k>CONVERT_BUF_SIZE) k=CONVERT_BUF_SIZE; n=read(fd,convert_buf,k); switch (clm_datum_format[fd]) { case snd_8_mulaw: for (j=0,jchar=convert_buf,m=(short *)(buf+total);j<n;j++,m++,jchar++) (*m) = mulaw[*jchar]; break; case snd_8_alaw: for (j=0,jchar=convert_buf,m=(short *)(buf+total);j<n;j++,m++,jchar++) (*m) = alaw[*jchar]; break; case snd_8_linear: for (j=0,jbyte=(char *)convert_buf,m=(short *)(buf+total);j<n;j++,m++,jbyte++) (*m) = (short) ((*jbyte) << 8); break; case snd_8_unsigned: for (j=0,jchar=convert_buf,m=(short *)(buf+total);j<n;j++,m++,jchar++) (*m) = (short) ((((int)(*jchar))-128) << 8); break; case snd_32_linear: lim = (n>>2); for (j=0,jword=(long *)convert_buf,m=(short *)(buf+total);j<lim;j++,m++,jword++) (*m) = (short) ((*jword) >> 16); break; case snd_24_linear: lim = ((n>>1)+(n>>2)); for (j=0,k=0,m=(short *)(buf+total);j<lim;j++,m++,k+=3) (*m) = (short) ((*((long *)(convert_buf+k))) >> 16); /* extra 8 because we're using (long *) -- low byte is garbage */ break; case snd_32_float: lim = (n>>2); for (j=0,jfloat=(float *)convert_buf,m=(short *)(buf+total);j<lim;j++,m++,jfloat++) (*m) = (short) (32768.0*(*jfloat)); /* DAJ sez float files go from -1.0 to 1.0 */ break; case snd_64_double: lim = (n>>3); for (j=0,jdouble=(double *)convert_buf,m=(short *)(buf+total);j<lim;j++,m++,jdouble++) (*m) = (short) (32768.0*(*jdouble)); break; } switch (siz) { case 1: total+=(n*2); break; case 2: total+=n; break; case 3: total+=((n>>2)+(n>>1)); break; case 4: total+=(n>>1); break; case 8: total+=(n>>2); break; } } return(total); } } #ifndef MAC int *makearray(len) { int *ip; ip = (int *)calloc(len,sizeof(int)); /* returns NULL (i.e. 0) if fails */ return ip; } freearray(int *ip) { free(ip); } #endif int setarray(int *arr, int i, int val) { arr[i]=val; return val; } int getarray(int *arr, int i) { return arr[i]; } int incarray(int *arr, int i, int val) { arr[i]+=val; return arr[i]; } cleararray1(int beg, int end, int *arr) { int *i,*last; last=arr+end; for (i=(arr+beg);i<=last;i++) *i=0; } clearchararray1(int beg, int end, char *arr) { char *i,*last; last=arr+end; for (i=(arr+beg);i<=last;i++) *i=0; } int clm_open_read(char *arg) { #ifndef MAC return(open (arg, O_RDONLY, 0)); #else return(open (arg, O_RDONLY)); #endif } int clm_open_write(char *arg) { int fd; #ifndef MAC if ((fd=open(arg,O_RDWR,0))==-1) fd=creat(arg,0666); else lseek(fd,0L,2); #else if ((fd=open(arg,O_RDWR))==-1) fd=creat(arg); else lseek(fd,0L,2); #endif return(fd); } int clm_create(char *arg) { #ifndef MAC return(creat(arg,0666)); #else return(creat(arg)); #endif } int clm_reopen_write(char *arg) { #ifndef MAC return(open(arg,O_RDWR,0)); #else return(open(arg,O_RDWR)); #endif } void clm_close(int fd) { close_clm_file_descriptors(fd); close(fd); } int clm_true_file_length(char *arg) { /* called in headers.lisp and next.lisp for error checks */ int fd; long int rtn; #ifndef MAC fd = open(arg,O_RDONLY,0); #else fd = open(arg,O_RDONLY); #endif rtn = lseek(fd,0L,2); close(fd); return rtn; } #ifndef MAC #define BUFLIM 512*1024 /* this should be 4 * file-buffer-size in defaults.lisp */ /* or, if quad files are in use, 8 * file-buffer-size */ #else #define BUFLIM 16384 /* should be 4 * file-buffer-size in defaults.lisp */ #endif /* static char charbuf[BUFLIM]; */ /* file I-O buffer */ /* doing it this way makes an enormous io.o file now */ /* I guess the new c compiler statically allocates it in */ /* the .o file, unlike the previous compiler. */ /* Now I wonder whether it matters that we never release */ #ifndef MAC static char *charbuf; static int char_ok = -1; check_charbuf (void) { if (char_ok == -1) charbuf = (char *)calloc((BUFLIM),sizeof(char)); char_ok = 0; } #else static char charbuf[BUFLIM]; check_charbuf (void) { } #endif int min (int x, int y) { if (x<y) return(x); return(y); } int ceiling (float x) { int y; y=x; if ((x-y)==0.0) return(y); return(y+1); } #ifndef MAC int checked_write(int fd, char *buf, int chars) { long lisp_call(int index); extern void perror(const char *); /* see /usr/include/sys/errno.h for actual errno values */ if (clm_write(fd,buf,chars) != chars) { perror("clm"); #ifndef AKCL lisp_call(7); /* see next56.lisp for the table of these constants -- 7=fatal write error */ #endif return -1; } return 0; } #else int checked_write(int fd, char *buf, int chars) { clm_write(fd,buf,chars); return 0; } #endif cwritez(int fd, int num) { int i,k,lim,curnum; check_charbuf(); lim=num*4; k=ceiling(lim/(BUFLIM)); curnum=min(lim,BUFLIM); clearchararray1(0,curnum-1,charbuf); for (i=0;i<=k;i++) { checked_write(fd,charbuf,curnum); lim=lim-(BUFLIM); curnum=min(lim,BUFLIM); } } /* assume data is stored as follows (32 bit words here, 8 bit bytes): /* high low high low /* A1 A2 /* A1 B1 */ crdmono(int fd, int beg, int end, int *buf) { int *i,*last; short *ii; int num,rtn; check_charbuf(); num=(end-beg+1)*2; /* file is packed, two samples per word */ rtn=clm_read(fd,charbuf,num); last=buf+beg+(rtn>>1); for (i=(buf+beg),ii=(short *)charbuf;i<last;i++,ii++) { *i = (int) (*ii); } if (rtn<num) { last=buf+end; for (;i<=last;i++) *i = 0; } } cwrtmono(int fd, int beg, int end, int *unpackedbuf) { int *i,*last; short *j; int num,lim; check_charbuf(); lim=(end-beg+1); num=lim*2; last=unpackedbuf+end; for (i=(unpackedbuf+beg),j=(short *)charbuf;i<=last;i++,j++) { (*j) = (short)(*i); } checked_write(fd,charbuf,num); } crdstereo(int fd, int beg, int end, int *bufa, int *bufb) { int *ia,*ib,*last; short *j,*k; int num,rtn; check_charbuf(); num=(end-beg+1)*4; rtn=clm_read(fd,charbuf,num); last=bufa+beg+(rtn>>2); for (ia=(bufa+beg),ib=(bufb+beg),j=(short *)charbuf,k=(short *)(charbuf+2); ia<last; ia++,ib++,j+=2,k+=2) { *ia= (int) (*j); *ib= (int) (*k); } if (rtn<num) { last=bufa+end; for (;ia<=last;ia++,ib++) { *ia=0; *ib=0; } } } cwrtstereo(int fd, int beg, int end, int *unpackedbufa, int *unpackedbufb) { int *ia,*ib,*last; short *j,*k; int num,lim; check_charbuf(); lim=(end-beg+1); num=lim*4; last=unpackedbufa+end; for (ia=(unpackedbufa+beg),ib=(unpackedbufb+beg),j=(short *)charbuf,k=(short *)(charbuf+2); ia<=last; ia++,ib++,j+=2,k+=2) { (*j) = (short)(*ia); (*k) = (short)(*ib); } checked_write(fd,charbuf,num); } crdquad(int fd, int beg, int end, int *bufa, int *bufb, int *bufc, int *bufd) { int *ia,*ib,*ic,*id,*last; short *j,*k,*l,*m; int num,rtn; check_charbuf(); num=(end-beg+1)*8; rtn=clm_read(fd,charbuf,num); last=bufa+beg+(rtn>>3); for (ia=(bufa+beg),ib=(bufb+beg),ic=(bufc+beg),id=(bufd+beg), j=(short *)charbuf,k=(short *)(charbuf+2),l=(short *)(charbuf+4),m=(short *)(charbuf+6); ia<last; ia++,ib++,ic++,id++,j+=4,k+=4,l+=4,m+=4) { (*ia)=(int)(*j); (*ib)=(int)(*k); (*ic)=(int)(*l); (*id)=(int)(*m); } if (rtn<num) { last=bufa+end; for (;ia<=last;ia++,ib++,ic++,id++) { *ia=0; *ib=0; *ic=0; *id=0; } } } cwrtquad(int fd, int beg, int end, int *unpackedbufa, int *unpackedbufb, int *unpackedbufc, int *unpackedbufd) { int *ia,*ib,*ic,*id,*last; short *j,*k,*l,*m; int num,lim; check_charbuf(); lim=(end-beg+1); num=lim*8; last=unpackedbufa+end; for (ia=(unpackedbufa+beg), ib=(unpackedbufb+beg), ic=(unpackedbufc+beg), id=(unpackedbufd+beg), j=(short *)charbuf, k=(short *)(charbuf+2), l=(short *)(charbuf+4), m=(short *)(charbuf+6); ia<=last; ia++,ib++,ic++,id++,j+=4,k+=4,l+=4,m+=4) { (*j)=(short)(*ia); (*k)=(short)(*ib); (*l)=(short)(*ic); (*m)=(short)(*id); } checked_write(fd,charbuf,num); } float absf(float x) { if (x>=0.0) return x; return(0.0-x); } float maxmagn(float x, float y) { if (x>absf(y)) return x; return (absf(y)); } float maxamparray(int size, float *arr) { float *i,*last; float maxa; maxa=arr[0]; last=arr+size; for (i=(arr+1);i<last;i++) maxa=maxmagn(maxa,*i); return maxa; } normarray(int size, float *arr) { float maxa; float *i,*last; maxa=maxamparray(size,arr); if (maxa==0.0) return; if (maxa==1.0) return; maxa=1.0/maxa; last=arr+size; for (i=arr;i<last;i++) *i=((*i)*maxa); } arrblt(int beg, int end, int newbeg, int *arr) { int *i,*j,*first; first=arr+end; for (i=(arr+beg),j=(arr+newbeg);i>=first;i--,j--) (*j)=(*i); } int absmaxarr(int beg, int end, int *arr) { int maxA,val; int *i,*last; last = arr+end; maxA = 0; for (i=arr+beg;i<=last;i++) { val = ((*i) & 0xffff); if (val & 0x8000) val = (65536 - val); if (val > maxA) maxA = val; } return maxA; } int last_time = 0; int get_last_time(void) { return last_time; } int timedabsmaxarr(int beg, int end, int *arr) { int j,maxA,val; int *i,*last; last = arr+end; maxA = 0; for (i=arr+beg,j=beg;i<=last;i++,j++) { val = ((*i) & 0xffff); if (val & 0x8000) val = (65536 - val); if (val > maxA) { maxA = val; last_time=j; } } return maxA; } int newtimedabsmaxarr(int beg, int end, int maxA, int *arr) { int minA; int *i,*first,*last; last = arr+end; first = arr+beg; minA = -maxA; for (i=first;i<=last;i++) { if (((*i) > maxA) || ((*i) < minA)) { maxA = (*i); if (maxA < 0.0) maxA = -maxA; minA = -maxA; last_time=(i-first); } } return maxA; }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.