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.