_REAL-TIME DATA AQUISITION_ by Mike Bunnell and Mitch Bunnell [LISTING ONE] /* dbuff.c Double buffering program for continuous reading from input and continuous writing to output */ #include #include #include extern char *malloc(); extern int errno; #define BSIZE 65536 /* size of each buffer */ struct xbuff { char buffer[BSIZE]; int count; int psem; int csem; int done; struct xbuff *other; }; /* Write function that is used by the output task */ outputr(p, prio) register struct xbuff *p; int prio; { int count; setpriority(0, getpid(), prio); while () { sem_wait(p->csem); /* wait for buffer to fill */ if (p->count <= 0) { sem_signal(p->psem); /* leave if finished or error */ break; Š } count = write(1, p->buffer, p->count); /* write output */ if (count <= 0) { /* exit if error on write */ p->done = 1; sem_signal(p->psem); break; } /* tell producer buffer has been emptied */ sem_signal(p->psem); p = p->other; } } /* Read function that is used by the input task */ inputr(p, prio) register struct xbuff *p; int prio; { int count; setpriority(0, getpid(), prio); do { /* wait for consumer to empty buffer */ sem_wait(p->psem); if (p->done) { break; } /* read from input and fill buffer */ count = read(0, p->buffer, BSIZE); p->count = count; /* tell consumer task buffer is filled */ sem_signal(p->csem); p = p->other; } while (count > 0); /* exit when no more data */ } main(argc, argv) int argc; char **argv; { register struct xbuff *buffa, *buffb; int inprio, outprio; /* default to current priority */ inprio = outprio = getpriority(0, 0); if (argc == 2) { /* Get input priority from command line if present */ inprio = atoi(argv[1]); Š } if (argc == 3) { /* Get output priority from command line if present */ inprio = atoi(argv[1]); outprio = atoi(argv[2]); } /* Allocate shared memory */ buffa = (struct xbuff *) smem_get( "buffa", (long)sizeof(struct xbuff), SM_READ | SM_WRITE); buffb = (struct xbuff *) smem_get( "buffb", (long)sizeof(struct xbuff), SM_READ | SM_WRITE); /* delete old semaphores if they exist */ sem_delete("buffac"); sem_delete("buffap"); sem_delete("buffbc"); sem_delete("buffbp"); buffa->csem = sem_get("buffac", 0); /* Create new semaphores to */ buffa->psem = sem_get("buffap", 1); /* control access to shared */ buffb->csem = sem_get("buffbc", 0); /* memory */ buffb->psem = sem_get("buffbp", 1); buffa->done = buffb->done = 0; buffa->other = buffb; buffb->other = buffa; /* Create another task to write. This task will read. */ if (fork() != 0) /* Create another task to */ inputr(buffa, inprio); /* write. This task will */ else /* read */ outputr(buffa, outprio); } [LISTING TWO] /* Reverb.c IIR filter program to add reverberation */ #include Š extern char *malloc(); ewrite(s) char *s; { write(2, s, strlen(s)); } /* Read the whole size read() under UNIX returns the amount it read. Last buffer is (biased) zero-filled. */ fullread(fd, buff, size) int fd; char *buff; int size; { int i, j; i = 0; do { j = read(fd, &buff[i], size - i); if (j <= 0) { /* This must be the last buffer of the file */ while (i < size) buff[i++] = 0x800; return -1; } i += j; } while (i < size); return size; } main(ac, av) int ac; char **av; { short *ibuff, *obuff; int delay; int i; int fd; int rundown; int rv; char *fn; register short *p, *q; if (ac > 2) { ewrite("usage: reverb [delay]\n (delay expressed in samples)\n"); exit(1); } if (ac == 2) delay = atoi(av[1]); else Š delay = 10240; /* make sure delay is multiple of 512 bytes */ delay -= delay & 511; /* make delay >= 512 andd <= 128K */ if (delay < 512) delay = 512; if (delay > 128*1024) delay = 128*1024; fd = 0; ibuff = (short *) malloc(delay * sizeof(*ibuff)); obuff = (short *) calloc(delay * sizeof(*obuff)); do { /* Read a buffer, but don't check error status yet */ rv = fullread(fd, ibuff, delay * sizeof(short)); /* Add the fresh input samples to the old samples, after dividing the old samples by 2 */ for (p = ibuff, q = obuff, i = 0; i < delay; ++i, ++p, ++q) *q = ((*q - 0x800) >> 1) + *p; /* Write the output reverbed buffer */ write(1, obuff, delay * sizeof(short)); } while (rv != -1); /* Allow sound in output buffer to "die down" */ for (rundown = 11; --rundown >= 0; ) { for (q = obuff, i = 0; i < delay; ++i) *q = (*q - 0x800) >> 1; write(1, obuff, delay * sizeof(short)); } } [LISTING THREE] /* reverse.c Write a file in reverse to standard output */ #include #include Š #include #include main(ac, av) int ac; char **av; { int fd; short buff[4096]; int rc; int i, j, t; long pos; struct stat s; ++av; if ((fd = open(*av, O_RDONLY, 0)) == -1) { perror(*av); /* exit if can't open file */ exit(1); } fstat(fd, &s); /* find the size of the file */ pos = s.st_size & 1; while (pos > 0) { /* See how many bytes can be read now */ if (pos < sizeof(buff)) rc = pos; else rc = sizeof(buff); pos -= rc; /* Seek back a block and read */ lseek(fd, pos, 0); read(fd, buff, rc); /* Reverse the samples in the block */ for (i = 0, j = (rc / 2) - 1; i < j; ++i, --j) { t = buff[i]; buff[i] = buff[j]; buff[j] = t; } /* Write the reversed block */ write(1, buff, rc); } close(fd); }