299 lines
8.2 KiB
Plaintext
299 lines
8.2 KiB
Plaintext
_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 <stdio.h>
|
|
#include <smem.h>
|
|
#include <sem.h>
|
|
|
|
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 <file.h>
|
|
Š
|
|
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 <file.h>
|
|
#include <types.h>
|
|
Š #include <time.h>
|
|
#include <stat.h>
|
|
|
|
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);
|
|
}
|
|
|