ftp.nice.ch/pub/next/unix/audio/cmix.s.tar.gz#/cmix/cmd/sndnorm.c

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

/*	Sndnorm automatically rescales the amplitude of any 
	soundfile to the max.  If the input soundfile is a floating
	point file, it automatically gets converted to an integer
	(playable) file.  If you want a floating point file to
	be produced, the fifth command line argument must be the
	letter f.

	Sndnorm determines the maximum amplitude of a sound file, 
	either by reading it from the header or by running getmaxamp().
	It then calculates the factor by which it will multiply all 
	the samples of the given sound file so that the maximum 
	amplitude is 32767.  Floating point files are converted to 
	playable (integer) files, rescaled so that the largest absolute
	value will be 32767, or 1 on a normalized scale of 0 to 1.    */

# include <stdio.h>

#ifndef LINT
static char SccsId[] = 	"@(#)sndnorm.c	1.2	12/3/85	IRCAM";
#endif

# include <sys/types.h>
# include <sys/stat.h>
# include <sys/file.h>
# include "../H/sfheader.h"

# define FAULT {fprintf(stderr,"Usage: sndnorm file [newname] [limit] [f]\n");\
	exit(1);}
# define HEADSIZE 1024

SFCODE	ampc = {
	SF_MAXAMP,
	sizeof(SFMAXAMP) + sizeof(SFCODE)
}; 

main(argc,argv)
int argc;
char *argv[];
{
	int sfd, error = 0, sfd2;
	struct stat st;
	SFMAXAMP *sfm, *getmaxamp();
	SFHEADER hd, hd2;
	int update, i, numbytes, sampcount;
	long sampframes, bytes, outbytes;
	float maxsamp = 0.0, multfac = 0.0, limiter = 1.0;
	float typemax;	
	char *buffer, *malloc(), *outbuf, newname[HEADSIZE];
	char *cp, *cp2, *getsfcode(), *getsfname();
	double atof();

	if(argc < 2 || argc > 5) 
		FAULT;
	if(argc > 2)
		if(!strcmp(argv[1],argv[2])) 
			FAULT;	
	if(argc >= 4)
		limiter = atof(argv[3]);
	if(limiter > 1.0 || limiter < 0.0) {
		fprintf(stderr,"Error in limiter...Range: 0.-1.\n");
		exit(1);
	}
	if(argc == 5)
		if(!strcmp(argv[4],'f')) 
			FAULT;
	update = 1;
	cp = getsfname(*++argv);
	if((sfd = open(cp,O_RDWR)) == -1) {
		if((sfd = open(cp,O_RDONLY)) == -1) {
			fprintf(stderr,"Can't find soundfile %s\n",cp);
			exit(1);	
		}		
		fprintf(stderr,"Can't update file %s - reading only!\n",cp);
		update = 0;
	}

	if(rheader(sfd,&hd)) {
		fprintf(stderr,"Bad header read for %s\n",cp);
		exit(1);
	}
	hd2 = hd;

	if(fstat(sfd,&st)) {
		fprintf(stderr,"Bad fstat() for %s\n",cp);
		exit(1);
	}

	typemax = 32767.;
	sampframes = sfbsize(&st) / sfchans(&hd) / sfclass(&hd);

/* If the maxamp is not to be found in the header, run getmaxamp()  */

	if(cp2 = getsfcode(&hd,SF_MAXAMP)) {
		sfm = (SFMAXAMP *)(cp2 + sizeof(SFCODE));
		if(!ismaxampgood(sfm,&st)) {
			fprintf(stderr,"Header info out of date. Updating\n");
			cp2 = NULL;
		}
	}

	if(cp2 == NULL)
		if((sfm = getmaxamp(sfd,update,0,sampframes)) == NULL) {
			fprintf(stderr,"Bad return from getmaxamp\n");
			exit(1);
		}

	printf("Maxamp for file %s:\n",*argv);
	for(i=0; i<sfchans(&hd); i++) {
		printf("channel %d = ",i + 1);
		if(sfmaxamp(sfm,i)) {
			printf(" %f at sample location %d",
				sfmaxamp(sfm,i)/typemax, sfmaxamploc(sfm,i));
			printf(", time:%6.3f\n",
				sfmaxamploc(sfm,i)/sfsrate(&hd));
		}	
		else    
			printf("silence\n");
	}

/* Ready to rescale; maximum amp has been determined*/	
	
	for(i=0; i<=sfchans(&hd); i++)
		if(sfmaxamp(sfm,i) > maxsamp)
			maxsamp = sfmaxamp(sfm,i);
	if(maxsamp == 0.) {
		fprintf(stderr,"Maxsamp is zero...Aborting sndnorm.\n");
		exit(1);
	}

	multfac = (typemax / maxsamp) * limiter;

/* Open output file	*/

	if(argc > 2)
		strcpy(newname,*(argv+1));
	else {
		strncpy(newname,*argv,HEADSIZE-sizeof(".rs"));
		strcat(newname,".rs");
	}

	if((sfd2 = open(getsfname(newname),O_CREAT|O_TRUNC|O_WRONLY,0644))<0) {	
	      fprintf(stderr,"Can't create soundfile %s\n",getsfname(newname));
		close(sfd);
		exit(1);
	}
	if(wheader(sfd2,&hd)) {/* copy header from source file onto new file */
		fprintf(stderr,"Failed to write new header.\n");
		close(sfd2);
		close(sfd);
		exit(1);
	}

/* Allocate buffers and execute rescaling of file */

	if(((buffer = malloc(SF_BUFSIZE)) == NULL) || 
		((outbuf = malloc(SF_BUFSIZE * 2)) == NULL)) {
		fprintf(stderr,"Bad call to malloc.\n");
		exit(1);
	}

	sflseek(sfd,0L,0); /* reset source soundfile ptr to start of samples*/

	bytes = sfbsize(&st);
	 
	while(bytes>0) {
		if((numbytes = read(sfd,buffer,SF_BUFSIZE))<0) {
			fprintf(stderr,"Bad read from source file\n");
			exit(1);
		}

		sampcount = numbytes/sfclass(&hd);
		outbytes = sampcount * SF_SHORT;  /* default output int files*/

		if(sfclass(&hd) == SF_FLOAT) {	/* floating point file in */
		   register float *floatout = (float *) outbuf, *bufend; 
		   register float *floatin = (float *) buffer, mf = multfac;
		   register short *shortout = (short *) outbuf, *sbufend; 

		   if(argc == 5) { 
			outbytes = sampcount * SF_FLOAT;  
			bufend = (float *) outbuf + sampcount;
			while(floatout < bufend)
				*floatout++ = *floatin++ * mf;
		   }
	           else {			
			sbufend = (short *) outbuf + sampcount;
			while(shortout < sbufend)
				*shortout++ = (short)(*floatin++ * mf);
		   }
		}
		else {   /* integer file input */	
		        register float *floatout = (float *) outbuf, *bufend; 
		        register short *shortin = (short *) buffer;
		        register float mf = multfac;
		        register short *shortout = (short *) outbuf, *sbufend;
		   if(argc != 5)  {    /* integer file in and out */
			sbufend =  (short *) outbuf + sampcount;
			while(shortout < sbufend)
				*shortout++ = *shortin++ * mf;
		   }
		   else {           /* integers in... floats out */ 
			outbytes = sampcount * SF_FLOAT;  
			bufend = (float *) outbuf + sampcount;
			while(floatout < bufend)
				*floatout++ = (float)(*shortin++ * mf);
		   }
		}
		if(write(sfd2,outbuf,outbytes) != outbytes) {
			fprintf(stderr,"Bad write to output file \n");
			exit(1);
		}
	   bytes -= numbytes;
	}

/* Update the header */

	for(i=0;i<=sfchans(&hd2);i++)
		sfmaxamp(sfm,i) = sfmaxamp(sfm,i) * multfac;
	sfmaxamptime(sfm) = time(0);
	if(putsfcode(&hd2,sfm,&ampc)) {
		fprintf(stderr,"Bad attempt to update new header.\n");
		exit(1);
	}
	sfclass(&hd2) = ((argc == 5) ? SF_FLOAT : SF_SHORT);
	lseek(sfd2,0,0);
	if(wheader(sfd2,&hd2)) {
		fprintf(stderr,"Failed to write new header to %s.\n",newname);
		close(sfd2);
		close(sfd);
		exit(1);
	}

/* Report new values */

	printf("\nNew maximum amplitude for file %s:\n",newname);
	for(i=0; i<sfchans(&hd2); i++) {
		printf("channel %d = ",i + 1); 
		printf(" %f at sample location %d",
			sfmaxamp(sfm,i)/typemax, sfmaxamploc(sfm,i));
		printf(", time:%6.3f\n",
			sfmaxamploc(sfm,i)/sfsrate(&hd2));
	}

	close(sfd2);
	close(sfd);
	exit(error);
}

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