This is ochan.c in view mode; [Download] [Up]
/*
* chan provides multichannel signal processing by demultiplexing its standard
* input, feeding each channel (through pipes) to one of several monophonic
* processing pipelines which run as parallel processes, remultiplexing the
* outputs of these processes, and writing the resulting multiplexed data stream
* on the standard output. A typical command form:
*
* cmusic stereo.sc | chan 2 "reverb .6 1000" "reverb .7 1131" | sndout -c 2
*
* takes the output of cmusic, separates the 2 channels, applies
* "reverb .6 1000" to the first channel, and "reverb .7 1131" to the second,
* then recombines the signal and pipes it to sndout. If only one process
* is specified for multiple channels, it is applied in parallel to each channel.
*/
#include <stdio.h>
#define MAXCHAN 4
#define ERR(msg) {fprintf(stderr,msg); exit(-1);}
#define MS(msg,val) {fprintf(stderr,msg,val);}
main(argc, argv) int argc; char *argv[]; {
register i, nchan;
int fdi[MAXCHAN][2], fdo[MAXCHAN][2];
FILE *pipe_in[MAXCHAN], *pipe_out[MAXCHAN];
float frame[MAXCHAN];
int data, status;
if(argc > 1) nchan = atoi(argv[1]);
if (argc != 3 && argc != nchan + 2)
ERR("Usage: chan N 'cmd' -or- chan N 'cmd1' ... 'cmdN'\n");
if(nchan < 2 || nchan > MAXCHAN)
ERR("chan: illegal number of channels\n");
for(i = 0; i < nchan; i++)
if( pipe( &fdi[i][0] ) < 0 || pipe( &fdo[i][0] ) < 0)
ERR("chan: pipe overflow\n");
/*
spouse process which reads output pipes, remuxes, and writes on stdout
*/
if( !fork() ){
for(i = 0; i < nchan; i++){
close( fdi[i][0] );
close( fdi[i][1] );
close( fdo[i][1] );
pipe_out[i] = fdopen( fdo[i][0], "r");
}
if( !isatty(1) )while(1){
for(i = 0; i < nchan; i++)
data = fread( &frame[i], sizeof(float), 1, pipe_out[i] );
if (data) fwrite( &frame[0], sizeof(float), nchan, stdout );
else exit(0);
} else while(1){
for(i = 0; i < nchan; i++)
data = fread( &frame[i], sizeof(float), 1, pipe_out[i] );
if (data) for(i = 0; i < nchan; i++) printf("%f\n", frame[i]);
else exit(0);
}
}
/*
processing children read stdin and write stdout, which are connected
to process input and process output pipes, respectively
*/
for(i = 0; i < nchan; i++)if( !fork() ){
/* connect stdin to process input pipes */
close( fdi[i][1] );
dup2( fdi[i][0], 0 );
close( fdi[i][0] );
/* connect stdout to process output pipes */
close( fdo[i][0] );
dup2( fdo[i][1], 1 );
close( fdo[i][1] );
/* execute processes */
if(argc == 3)
execlp( "/bin/csh", "csh", "-c", argv[2], 0);
else
execlp( "/bin/csh", "csh", "-c", argv[i+2], 0);
ERR("chan: We NEVER come here!");
}
/*
parent process reads its stdin, demuxes, and writes on input pipes
of each parallel process
*/
for(i = 0; i < nchan; i++){
close( fdo[i][0] );
close( fdo[i][1] );
close( fdi[i][0] );
if( (pipe_in[i] = fdopen( fdi[i][1], "w") ) == NULL)
ERR("chan: fdopen failed\n");
}
if( !isatty(0) ) while( fread( &frame[0], sizeof(float), nchan, stdin ) ){
for( i = 0; i < nchan; i++ )
if( !fwrite( &frame[i], sizeof(float), 1, pipe_in[i] ) )
ERR("chan: unable to write process input pipes\n");
} else wait( &status );
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.