ftp.nice.ch/pub/next/unix/audio/cmusic.bs.N.tar.gz#/src/sigsf/mixsf.c

This is mixsf.c in view mode; [Download] [Up]

#include <math.h>
#include <stdio.h>
#include <carl/sndio.h>
#include <carl/carl.h>
#include <carl/procom.h>

extern int sferror;
extern CSNDFILE *rootsfd;

/*-------------------------------------------------------
			mixsf.c

This is a program for performing simple arithemetic operations
	on soundfiles (e.g., addition, subtraction, multiplication,
	and division).  One soundfile is piped in on stdin,
	the other is named on the command line, and the result
	is piped out on stdout.  The program also allows for
	simple interleaving of soundfiles (e.g., mono to stereo).
	The program runs exactly as long as there is input on
	stdin.

To compile:	cc mixsf.c -lsf -lcarl -lm

-------------------------------------------------------*/

main(argc, argv)
	int argc;
	char **argv;
{

	float fsndi();

	float	in1,		/* input from first file */
		in2,		/* input from second file */
		out,		/* output */
		max = 0.,	/* maximum output value */
		att = 1.,	/* soundfile input scale factor */
		fac = 1.,	/* output scale factor */
		srate;		/* sample rate on stdin */

	int	add = 0,	/* flag for addition */
		sub = 0,	/* flag for subtraction */
		mul = 0,	/* flag for multiplication */
		div = 0,	/* flag for division */
		mux = 0,	/* flag for interleaving */
		nchan;		/* number of channels on stdin */

	long	i,		/* counter for soundfile samples */
		beg = 0,	/* first sample of soundfile */
		end = 0,	/* last sample of soundfile */
		del = 0;	/* delay before beginning of soundfile */

	CSNDFILE *sfd, *opensf();

	char ch;

	char *cbeg = NULL, *cend = NULL, *cdur = NULL, *cdel = NULL;

	char *file = "test";

	char	cbuf[72];	/* buffer for strings to write to header */

	char	*dbuf;		/* buffer for strings to read from header */

	PROP	*proplist;	/* from header on stdin */

/* Interpret commandline by calling dgl's subroutine crack. */

	if (isatty(0)) usage(1);

	while ((ch = crack(argc, argv, "b|e|d|q|g|x|iacmsh", 0)) != NULL) {
		switch (ch) {
			case 'a':  add = 1; break;
			case 's':  sub = 1; break;
			case 'm':  mul = 1; break;
			case 'c':  div = 1; break;
			case 'i':  mux = 1; break;
			case 'x':  fac = sfexpr(arg_option,1.0); break;
			case 'g':  att = sfexpr(arg_option,1.0); break;
			case 'b': cbeg = arg_option; break;
			case 'e': cend = arg_option; break;
			case 'd': cdur = arg_option; break;
			case 'q': cdel = arg_option; break;
			case 'h':  usage(0);
			default:   usage(1);	/* this exits with error */
		}
	}

/* Read header from stdin. */

	if ((proplist = getheader(stdin)) != NULL) {	/* there is a header */
		noautocp();				/* suppress hdr copy */

		if ((dbuf=getprop(stdin, H_SRATE)) != NULL) srate = atof(dbuf);
		if ((dbuf=getprop(stdin, H_NCHANS)) != NULL)nchan = atoi(dbuf);
	}

/* Read in second soundfile. */

	if (arg_index < argc)
		file = argv[arg_index];
	else fprintf(stderr,"mixsf: soundfile #2 not specified\n");

	/* open sound file */
	if ((sfd = opensf(file, "-r")) == NULL) { 
		fprintf(stderr,"mixsf: opensf failed on %s\n", file);
		(void) sfallclose(); 
		exit(1); 
	}

	/* calculate times */
	if (cbeg != NULL) 
		beg = sfexpr(cbeg, sfd->sr)*sfd->nc;
	if (cend != NULL)
		end = sfexpr(cend, sfd->sr)*sfd->nc;
	else if (cdur != NULL)
		end = sfexpr(cdur, sfd->sr)*sfd->nc + beg;
	if (cdel != NULL)
		del = sfexpr(cdel, sfd->sr)*sfd->nc;

	/* check boundaries */
	if (beg < 0 || beg >= sfd->fs) {
		fprintf(stderr, "mixsf: begin time out of range\n");
		quit();
	}
	if (end < 0 || end >= sfd->fs) {
		fprintf(stderr, "mixsf: end time out of range\n");
		quit();
	}
	if (end == 0)
		end = sfd->fs;

	i = beg - del;	/* counter for soundfile samples */

/* Write header to stdout. */

	if (srate != sfd->sr)
	fprintf(stderr,"mixsf: warning - incompatible sample rates\n");

	if (nchan != sfd->nc)
	fprintf(stderr,"mixsf: warning - incompatible mono/stereo\n");

	if (mux){
		nchan += sfd->nc;
		sprintf(cbuf,"%d",nchan);
		rmprop(stdin,H_NCHANS);
		addprop(stdin,H_NCHANS,cbuf);
	}

	cpoheader(proplist,stdout);
	putheader(stdout);

/* Main loop:  Program runs exactly as long as there is input on stdin. */

	if (mux){
		while (getfloat(&in1) > 0) {
			if ((i < end) && (i >= beg))
				in2 = fsndi(sfd, i++);
			else in2 = 0.;
			if (sferror)
				quit();
			if (att != 1.)
				in2 *= att;
			if (fac != 1.){
				in1 *= fac;
				in2 *= fac;
			}
			putfloat(&in1);
			putfloat(&in2);
		}
	}

	else {
		while (getfloat(&in1) > 0) {
			if ((i < end) && (i >= beg))
				in2 = fsndi(sfd, i++);
			else {
				in2 = 0.;
				i++;
			}
			if (sferror)
				quit();
			if (att != 1.)
				in2 *= att;
			if (sub)
				 out = fac * (in1 - in2);
			else
				if (mul)
					out = fac * in1 * in2;
				else
					if (div){
						if (in2 > .001)
							in2 = 1./in2;
						else
							in2 = 1000.;
						out = fac * in1 * in2;
					}
					else
						out = fac * (in1 + in2);
			if (out > 1.)
				max = out;
			if (out < -1.)
				max = - out;
			putfloat(&out);
		}
	}
	
	if (max >= 1.)
		fprintf(stderr,"mixsf: clipping - max output = %g\n",max);

	/* close all open files */
	(void) sfallclose();

	flushfloat();

	exit(0);
}

usage(exitcode)
	int exitcode;
{
	fprintf(stderr,"%s%s%s%s%s%s%s%s%s%s%s%s%s",
		"\nusage: mixsf [flags] soundfile < floatsams > floatsams\n",
		"\nflags:\n",
		"\ta: add soundfile to stdin\n",
		"\ts: subtract soundfile from stdin\n",
		"\tm: multiply soundfile by stdin\n",
		"\tc: divide stdin by (energy) soundfile (for AGC)\n",
		"\ti: interleave soundfile with stdin\n",
		"\tx = output scale factor to avoid clipping (1.)\n",
		"\tg = input gain factor for soundfile (1.)\n",
		"\tb = begin time in soundfile (first sample to use) (0.)\n",
		"\te = end time in soundfile (last sample to use) (end)\n",
		"\td = duration of soundfile (end - begin)\n",
	"\tq = quiet time before soundfile (delay before first sample)(0)\n\n");
	exit(exitcode);
}

quit() {
	fprintf(stderr, "exiting\n");
	(void) sfallclose(); 
	exit(1); 
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.