#define UNIXFILES #include #include #include #include #include #include #include #include #include "sfheader.h" #include #include "virgil.h" short fid; float tick; #define FUDGE 0 /* guess at how long it takes to read 64k bytes in */ float tval = FUDGE; /* fudge to allow time to read in buffers */ main(argc,argv) int argc; char *argv[]; { char *buffer,*cp,*sfname; long nsamps,blksize,originalsize,sf,result,sfd,i,nskips,chans; int status,shutup(),pid,(*oldint)(),(*oldquit)(),rtn,w,errno; int loadword(), dmaword; float srate,dur,pdur,inskip; double atof(); SFHEADER sfh; struct stat sfst; srate=dur=pdur=inskip=chans=tick=0; if(argc == 1) { printf("usage: play [-s skip] [-d dur] [-r srate] [-c nchans] [-b beats] file_name\ndefaults:s=0, dur=all, beats=0, r&c read from header\n"); exit(1); } while((*++argv)[0] == '-') { argc -= 2; /* Take away two args */ for(cp = argv[0]+1; *cp; cp++) { switch(*cp) { /* Grap options */ case 'r': srate = atof(*++argv); printf("Sampling rate reset to %f\n",srate); break; case 'd': pdur = atof(*++argv); printf("Play duration is %f\n",pdur); break; case 's': inskip = atof(*++argv); tval += inskip; printf("Input skip is %f\n",inskip); break; case 'c': chans = atoi(*++argv); printf("Number of channels reset to %d\n", chans); break; case 'b': tick = atof(*++argv); printf("Beat turned on every %f seconds\n",tick); break; default: printf("Don't know about option: %c\n",*cp); } } } while(argc-- > 1) { sfname = *argv++; readopensf(sfname,sfd,sfh,sfst,"play",result) if(result < 0) exit(0); printf("name: %s sr: %f nchans: %d class: %d\n",sfname, sfsrate(&sfh),sfchans(&sfh),sfclass(&sfh)); srate = (srate ? srate : sfsrate(&sfh)); chans = (chans ? chans : sfchans(&sfh)); originalsize = ((sfst.st_size - SIZEOF_HEADER)/SF_SHORT)/chans; dur = pdur ? pdur : ((float)originalsize/srate) - inskip; printf("play duration = %f\n",dur); if((inskip + dur) > (.01 + originalsize/srate)) { printf("The file is not that big. Duration = %f\n",dur); exit(1); } nsamps=dur * srate * chans; nskips = inskip * srate * (float)chans * SF_SHORT; nskips -= nskips % (chans * SF_SHORT); if(sflseek(sfd,nskips,0) == -1) { printf("Bad lseek on soundfile\n"); exit(1); } blksize=sfst.st_blksize; if(sfclass(&sfh) != 2) { printf("You can't listen to this file, not made of integers.\n"); exit(1); } if(tick) startclock(tick); if((int)srate == 14000) chans *= 8; /* uses DACs 3&4 for 14k */ fflush(stdout); if ((pid = fork()) == 0) { (void) signal(SIGINT,SIG_IGN); (void) signal(SIGQUIT,SIG_IGN); (void) signal(SIGTSTP,SIG_IGN); (void) signal(SIGSTOP,SIG_IGN); if((dmaword = loadword(srate,chans,DTOA)) < 0) { perror("loadword"); exit(1); } i=dsdac42(sfd,nsamps,blksize,dmaword); exit(i); } if(tick) stopclock(); oldint = signal(SIGINT, shutup); oldquit = signal(SIGQUIT, shutup); /* wait for process, or interrupts */ while ((w = wait(&status)) != pid) { if (w == -1) { if (errno == EINTR) continue; break; } } signal(SIGINT,oldint); signal(SIGQUIT,oldquit); close(sfd); if(tick) tval = FUDGE + inskip; /* reset for next file */ } } shutup() { int fid; if((fid = open("/dev/drreset0",0)) < 0) perror("shutup"); } extern errno; /* how many buffers */ # define UBSIZE 4 # define BP16BIT 2 short *dsbuf; char *ddserrs[] = { "missing arguments/parameters", "converters in use", "buffer size wasn't modulo bsize", "buffer size was too small", "disk error", "converter error", "dsreset clobbered us", "sync time out", "" }; dsdac42(sfd, nsamps, blksize, dmaword) int sfd; long nsamps; /* number of samples to convert */ long blksize; /* File system block size */ { struct ds_seq dsseq; struct ds_err dserr; struct ds_fs dsf; register int dacfid, cnt=0, erno; short j; /* printf("DSCOUNT=%D ", nsamps * BP16BIT); */ if (nsamps < 1) { fprintf(stderr, "dsdac: can't convert 0 samples!\n"); return(-1); } /* ds driver will use this buffer for sample data transfer */ if (dsbuf == NULL) if ((dsbuf = (short *) valloc((unsigned) blksize * UBSIZE)) == NULL) { perror("valloc"); return(1); } while ((dacfid = open("/dev/dr", 2)) < 0) if (errno != ENXIO) { perror("dsdac:open"); return(-1); } dsf.bnosiz = sfd; if (ioctl(dacfid, DS42BSD, &dsf) == -1) { perror("dsblks"); goto errout; } dsf.bnosiz = dmaword; /* just to set parameters for my board */ if (ioctl(dacfid, DSWORD, &dsf) == -1) { perror("dsword"); goto errout; } if (write(dacfid, (char *) dsbuf, nsamps * BP16BIT) == -1) { perror("write"); if (ioctl(dacfid, DSERRS, &dserr) == -1) { perror("dserrs"); goto errout; } switch (dserr.errors) { case EDS_ARGS : erno = 0; break; case EDS_ACC : erno = 1; break; case EDS_MOD : erno = 2; break; case EDS_SIZE : erno = 3; break; case EDS_DISK : erno = 4; break; case EDS_CERR : erno = 5; break; case EDS_RST : erno = 6; break; default: erno = 8; break; } fprintf(stderr, "%d %s dmacsr=%o, asccsr=%o, errors=%o\n",erno, ddserrs[erno], dserr.dma_csr & ((u_short) -1), dserr.asc_csr & ((u_short) -1), dserr.errors & ((u_short) -1)); puts("E_DACS"); goto errout; } if(close(dacfid)) printf("Bad close\n"); free((char *) dsbuf); puts("!"); return(0); errout: free((char *) dsbuf); close(dacfid); return(1); } struct itimerval *value; startclock(tick) float tick; { int telltime(),msecs; char *malloc(); value = (struct itimerval *)malloc(sizeof(value)); value->it_value.tv_sec = value->it_interval.tv_sec = (int)tick; msecs = (int)(1000000. * (tick - (float)value->it_value.tv_sec)); value->it_value.tv_usec = value->it_interval.tv_usec = msecs; (void) signal(SIGALRM,telltime); setitimer(ITIMER_REAL,value,value); } telltime() { static int position = 0; if(position++ < 8 ) printf(" %5.3f",tval); else {printf(" %5.3f\n",tval); position = 0; } fflush(stdout); tval += tick; } stopclock() { value->it_value.tv_sec = value->it_interval.tv_sec = 0; } #include "virgil.h" loadword(opsrate,opchans,function) float opsrate; { int val = opsrate; int word; switch(val) { case 7000 : word = CLOCK56 | DIV8; break; case 7500 : word = CLOCK60 | DIV8; break; case 14000 : word = CLOCK56 | DIV4; break; case 15000 : word = CLOCK60 | DIV4; break; case 28000 : word = CLOCK56 | DIV2 ; break; case 30000 : word = CLOCK60 | DIV2 ; break; case 56000 : word = CLOCK56 | DIV1 ; break; case 1 : word = PULSE; printf(" Use pulse generator. Make sure it is on.\n"); break; default : printf(" Not one of my available sampling rates, tryagain."); return(-1); } switch(opchans) { case 1 : word |= CHAN1; break; case 2 : word |= CHAN1 | CHAN2 ; break; case 4 : word |= CHAN1 | CHAN2 | CHAN3 | CHAN4 ; if(function == ATOD) { printf("You cannot do A-D in 4 channels\n"); return(-1); } break; case 8 : word |= CHAN3 ; /* to use for 14k conversion */ break; case 16 : word |= CHAN3 | CHAN4 ; /* to use for 14k stereo conversion */ break; default : printf( " Bad channel specification \n"); return(-1); } return(word | (function == ATOD ? function | IOLINK : function)); }