/* record -- Dump a soundfile from DAC (/dev/ai0) to disk * * Revisions: * 1.1 12/16/87 -- Basic record by bgg, dressed-up by jwp * (error handling, signal traps, multiple files) * 1.3 5/88 -- forking process to handle new driver, smaller * DMA buffers, ignores last block (disk protection) -- bgg * * NOTE: the soundfile must physically exist on disk before recording * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "aireg.h" #include "aivar.h" #include #include #include "sfheader.h" #define CLOCK1 14400000 #define CLOCK2 14318180 int devfd; struct aud_conv stuff; main(argc,argv) int argc; char *argv[]; { int sffd,f,nchannels; float srate; short peakval,csr_stat = 0x0000; struct stat sfst; SFHEADER hd; int srflag = 0; int noheader = 0; void byebye(),getinfo(); int build_srint(); extern char *optarg; extern int optind; int o,badopt = 0; float atof(); int id,status; char nothing; system("sync;sync"); /* not sure if this helps */ /* Parse some options: */ while ((o = getopt(argc,argv,"r:n")) != EOF) { switch(o) { case 'r': srate = atof(optarg); fprintf(stderr,"sampling rate set to %f\n",srate); srflag = 1; break; case 'n': getinfo(&srate,&nchannels); noheader = 1; break; default: badopt++; break; } } if (argc == optind || badopt) faterr("Usage: record [-r [S. RATE] -n ] soundfile ..."); /* Open up the converter and soundfile */ if ((devfd = open("/dev/ai0",0,2)) < 0) faterr("Can't open converter device"); if ((sffd = open(argv[optind],0,2)) < 0) { fprintf(stderr,"Can't open soundfile: %s\n",argv[optind]); return(-1); } if (!noheader) { /* Be sure this is a soundfile, and that it has short samples, not floats. */ rheader(sffd,&hd); close(sffd); if (!ismagic(&hd)) { printf("this isn't a soundfile! -- %s\n",argv[optind]); return(-7); } if ( sfclass(&hd) != SF_SHORT ) { printf("use short integers for recording!\n"); return(-7); } if (!srflag) srate = (float)sfsrate(&hd); nchannels = sfchans(&hd); sffd = open(argv[optind],0,2); } fstat(sffd,&sfst); if (sfst.st_size < 8192) { fprintf(stderr,"file too small -- block out at least 8k bytes before recording\n"); exit(-1); } stuff.a_nbytes = sfst.st_size; stuff.a_fd = sffd; stuff.a_flags = 0; stuff.a_numdbs = 2; stuff.a_nchans = nchannels; stuff.a_srate = build_srint(srate,nchannels); stuff.a_scanflag = 0; stuff.a_bufskip = 0; stuff.a_byteskip = 0; if (!noheader) stuff.a_bufskip = 1; /* skip one buffer for header */ /* ignore signals, if record is interrupted inode may lock */ signal(SIGHUP,SIG_IGN); signal(SIGINT,SIG_IGN); signal(SIGQUIT,SIG_IGN); signal(SIGBUS,SIG_IGN); signal(SIGSEGV,SIG_IGN); signal(SIGTERM,SIG_IGN); signal(SIGTSTP,SIG_IGN); f = ioctl(devfd,AIO_SET_ADC,&stuff); if (f < 0) { printf("yikes! timeout error -- check to see that ds16 is on, try again, etc.\n"); ioctl(devfd,AIO_RESET,&stuff); exit(-1); } /* record */ if ( (id = fork() ) == 0 ) { /* child does the recording */ printf("hit to start recording\t"); scanf("%c",¬hing); if (ioctl(devfd,AIO_GO,&stuff) < 0) { fprintf(stderr,"Error on conversion (errno = %d) ",errno); fprintf(stderr,"-- try again\n"); ioctl(devfd,AIO_RESET,&stuff); close(devfd); exit(-1); } } wait(&status); if (status == -1) return(-1); close(devfd); sleep(1); /* wait a sec before going to next file */ } void byebye(sig) int sig; { fprintf(stderr,"record: Terminated (signal %d)\n",sig); ioctl(devfd,AIO_RESET,&stuff); signal(SIGINT,SIG_DFL); signal(SIGQUIT,SIG_DFL); signal(SIGTERM,SIG_DFL); signal(SIGTSTP,SIG_DFL); close(devfd); exit(0); } /* convert sampling rate to ds16 lo and hi SR register format */ build_srint(desired,nchans) float desired; int nchans; { float basis1,basis2,fbase1,fbase2,basis; int ibase1,ibase2,ibasis,result,tbase = 0; short lo,hi,tophi; char *byter; basis1 = CLOCK1/desired; basis2 = CLOCK2/desired; ibase1 = basis1; ibase2 = basis2; fbase1 = basis1 - (float)ibase1; fbase2 = basis2 - (float)ibase2; if (ibase1 > 4096) { if (ibase2 > 4096) { fprintf(stderr,"sampling rate too low\n"); exit(-1); } else { tbase = CLOCK2; basis = basis2; } } else { if (ibase2 > 4096) { tbase = CLOCK1; basis = basis1; } } if (tbase == 0) { if (fbase1 < fbase2) { if ( ABS(fbase2 - .99999) < fbase1 ) { tbase = CLOCK2; basis = basis2; } else { tbase = CLOCK1; basis = basis1; } } else { if ( ABS(fbase1 - .99999) < fbase2 ) { tbase = CLOCK1; basis = basis1; } else { tbase = CLOCK2; basis = basis2; } } } ibasis = basis; if ( (basis - (float)ibasis) > 0.5 ) basis += 1.0; ibasis = basis; result = 4096 - ibasis; if (result < 0) { fprintf(stderr,"bad SR selection, result = %d\n",result); exit(-1); } byter = (char *)&result; byter += 2; hi = (*byter & 0x00ff) | ( (*byter << 8) & 0xff00 ); byter += 1; lo = (*byter & 0x00ff) | ( (*byter << 8) & 0xff00 ); tophi = 0x0000; if ( (int)desired*nchans > 50000 ) tophi = 0x4040; if (tbase == CLOCK2) tophi = tophi | 0x1010; hi = hi | tophi; result = (lo & 0x0000ffff) | ( (hi << 16) & 0xffff0000 ); return(result); } void getinfo(sr,nch) float *sr; int *nch; { printf("enter sampling rate: "); scanf("%f",sr); printf("enter number of channels: "); scanf("%d",nch); } faterr(msg) char *msg; { fprintf(stderr,"%s\n",msg); close(devfd); exit(1); }