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

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

/*
   It will create an integer file called  filename.short if you don't
   specify an output file. */
/* could also make this into a neat general purpose alteration program ?*/

/* TODO create option to skip on input and output, and specify duration and 
   optional peak */

#include "../H/sfheader.h"
#include "rescale.h"
#include <stdio.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
#include <errno.h>
#define  BUFSIZE 32768

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

static SFCODE	commentcode = {
	SF_COMMENT,
	MINCOMM + sizeof(SFCODE)
	};


main(argc,argv)

int argc;
char *argv[];

{
	SFMAXAMP sfm,sfmnew;
	SFCOMMENT sfcm;
	SFHEADER sfh1,sfh2;
	SFCODE *sizer;
	struct stat sfst1,sfst2;

	char *cp,*sfin,*sfout,*getsfcode();
	double atof();
	short outbuffer[BUFSIZE];
	float inbuffer[BUFSIZE];
	int i,n,bytes,words,inbytes,outbytes,sf1,sf2,result,readbytes,durbytes;
	int replace,empty,skipbytes,outskipbytes,newfile;
	float opeak,factor,skpin,dur,newpeak,outskip;
	char command[256];
	char newname[128];
	char *point,*point2,*strcat();
	short *bufp;
	float Oresult = 32767;

	if(argc == 1) {
usage:		printf("usage: -s inskip -d dur -o outskip -p peakamp -P desired peak -r [write over floating-point file] -e emptybuffers_at_end -z [create new file] -f factor inputfile [outputfile]\n");
		printf("defaults: s=0, d=to_eof, o=0, p=input_peak, e=1, P=32767, f=P/input_peak write over old file, outputfile=inputfile.short\n");
		exit(0);
		}
	replace=newfile=skpin=dur=newpeak=outskip=factor=0;

	empty = 1;  /* defaults to 1 empty buffers at end*/

	while((*++argv)[0] == '-') {
		argc -= 2; /* Take away two args */
		for(cp = argv[0]+1; *cp; cp++) {
			switch(*cp) { /* Grap options */
			case 'r':
				replace = 1;
				printf("Writing over floating-point file\n");
				break;
			case 's': 
				skpin = atof(*++argv);
				printf("input skip = %f\n",skpin);
				break;
			case 'd': 
				dur = atof(*++argv);
				printf("rescale duration = %f\n",dur);
				empty = 0; /* no empty buffers for splice */
				break;
			case 'f':
				factor = atof(*++argv);
				printf("specified factor = %f\n",factor);
				break;
			case 'p': 
				newpeak = atof(*++argv);
				printf("specified peak = %f\n",newpeak);
				break;
			case 'P':
				Oresult = atof(*++argv);
				printf("resultant peak = %f\n",Oresult);
				break;
			case 'o': 
				outskip = atof(*++argv);
				printf("output skip =  %f\n",outskip);
				break;
			case 'e':
				empty = atof(*++argv);
				printf("write %d empty buffers at end\n",empty);
				break;
			case 'z':
				newfile = 1;
				break;
			default:
				printf("uh-oh, unkown option\n");
				goto usage;
			}
		}
	}
	sfin = argv[0];
	sfout = argv[1];
	readopensf(sfin,sf1,sfh1,sfst1,"rescale",result);
	if(result < 0) {
		close(sf1);
		exit(1);
	}
	/* do input skip on input file*/
	if(skipbytes = 
		skpin * sfclass(&sfh1) * sfsrate(&sfh1) * sfchans(&sfh1)) {
		skipbytes -= skipbytes % (sfclass(&sfh1) * sfchans(&sfh1));
			/* make sure it lands on sample block */
		if(sflseek(sf1,skipbytes,0) == -1) {
			printf("Bad skip on input file\n");
			exit(1);
		}
	}

	printsf(&sfh1);
	if(sfclass(&sfh1) == SF_SHORT) {
		printf("Note: Input file has short integers.\n");
	}

	cp = getsfcode(&sfh1,SF_MAXAMP);
	bcopy(cp + sizeof(SFCODE), (char *) &sfm, sizeof(SFMAXAMP));
	for(i=0,opeak=0; i<sfchans(&sfh1); i++) 
		if(sfmaxamp(&sfm,i) > opeak) opeak = sfmaxamp(&sfm,i);
	opeak = newpeak ? newpeak : opeak;
	if(!opeak) {
		printf("Sorry, but I have no peak amplitude for this file.\nPut one in with sfhedit, sndpeak, or use the -p flag in rescale.\n");
		close(sf1);
		exit(-3);
		}
	printf("Peak amplitude of input file is %e\n",opeak);
	if(!factor) factor = Oresult/opeak;
	printf("factor = %f\n",factor);

	if((cp=getsfcode(&sfh1,SF_COMMENT)))  {
	sizer = (SFCODE *) cp;
	bcopy(cp + sizeof(SFCODE) , (char *) &sfcm, sizer->bsize);
	}
	if(replace) sfout=sfin;
	/* added to allow compatibility with new i/o -- DAS */
#if defined(NeXT) || defined(NEXT)
	nsfmagic(&sfh2) = SND_MAGIC;
	sfmagic(&sfh2) = SF_MAGIC;
#endif
	newrwopensf(sfout,sf2,sfh2,sfst2,"rescale",result,2);
	if(result < 0) {
		if(sfout == NULL) {
			point = sfin;
			if(sfclass(&sfh1) == SF_FLOAT) 
				point = strcat(sfin,".short");
			else
				point = strcat(sfin,".xshort");
		}
		else
			point = sfout;

		sfmagic(&sfh2) = SF_MAGIC;
		sfclass(&sfh2) = SF_SHORT;
		sfchans(&sfh2) = sfchans(&sfh1);
		sfsrate(&sfh2) = sfsrate(&sfh1);
		if((sf2 = open(point,O_CREAT|O_RDWR,0644)) < 0 ) {
			printf("Can't open file %s\n",point);
			exit(-2);
		}
		if(newfile) ftruncate(sf2,SIZEOF_BSD_HEADER);

		for(i=0; i<sfchans(&sfh2); i++) {
			sfmaxamp(&sfmnew,i)=sfmaxamp(&sfm,i)*factor;
			sfmaxamploc(&sfmnew,i)=sfmaxamploc(&sfm,i);
		}
		sfmaxamptime(&sfmnew) = sfmaxamptime(&sfm);
		putsfcode(&sfh2,&sfmnew,&ampcode);
		if (putsfcode(&sfh2,&sfcm,&commentcode) < 0) {
			printf("comment didn't get written, sorry!\n");
			exit(-1);
		}
		printf
			("\nCreating output file: %s\n",point);
		if(wheader(sf2,(char *)&sfh2)) {
	       		printf("Can't seem to write header on file %s\n"
					,point);
			perror("main");
			exit(-1);
		}
	}
	else if(!replace) printsf(&sfh2);
	if(!replace && (sfclass(&sfh2) != SF_SHORT)) {
		printf("Output file must have short integers.\n");
		exit(-1);
	}
	/* do output skip*/
	if(outskipbytes = 
		  outskip * sfclass(&sfh2) * sfsrate(&sfh2) * sfchans(&sfh2)) {
		outskipbytes -= 
			      outskipbytes % (sfclass(&sfh2) * sfchans(&sfh2));
			/* make sure it lands on sample block */
		if(sflseek(sf2,outskipbytes,0) == -1) {
			printf("Bad skip on output file\n");
			exit(1);
		}
	}

	readbytes = inbytes = BUFSIZE * sfclass(&sfh1);

	durbytes = dur * sfclass(&sfh1) * sfchans(&sfh1) * sfsrate(&sfh1);
	
	fflush (stdout);
	fprintf(stderr,"Rescaling....\t");

	bufp = (short *)inbuffer;

	while(1) {
		if(dur) {
			inbytes = (durbytes > readbytes) ? inbytes : durbytes;
			durbytes -= inbytes;
		}
		if((bytes = read(sf1,(char *)inbuffer,inbytes)) <= 0) {
			printf("reached eof on input\n");
			close(sf1);
			break;
		}
		words = bytes/sfclass(&sfh1);
		outbytes = words * SF_SHORT;

		if(sfclass(&sfh1) == SF_SHORT)
//			for(i=0; i<words; i++) 
			for(i=words-1; i>=0; i--)
				outbuffer[i] = (short)((float)bufp[i] * factor);
		else
		//	for(i=0; i<words; i++)
			for(i=words-1; i>=0; i--)
				outbuffer[i] = (short) (inbuffer[i] * factor);
		if(write(sf2,(char *)outbuffer,outbytes) != outbytes) {
			printf("Bad write on output file\n");
			close(sf1);
			close(sf2);
			exit(0);
		}
	}
	/* write  empty buffers */
	for(i=0; i<words; i++) outbuffer[i] = 0;
	for(i=0; i<empty; i++)
		if(n=write(sf2,(char *)outbuffer,outbytes) != outbytes) {
			printf("Bad write on output file\n");
			close(sf2);
			exit(0);
		}
	if(replace) {
		i = lseek(sf2,0,1);
		if(ftruncate(sf2,i) < 0) 
			printf("Bad truncation\n");
		lseek(sf2,0,0);
		for(i=0; i<sfchans(&sfh2); i++) {
			sfmaxamp(&sfmnew,i)=sfmaxamp(&sfm,i)*factor;
			sfmaxamploc(&sfmnew,i)=sfmaxamploc(&sfm,i);
		}
		sfmaxamptime(&sfmnew) = sfmaxamptime(&sfm);
		putsfcode(&sfh2,&sfmnew,&ampcode);
		sfclass(&sfh2) = SF_SHORT;
		if(wheader(sf2,(char *)&sfh2)) {
       			printf("Can't seem to write header on file %s\n"
					,point);
			perror("main");
			exit(-1);
		}
		if(fsync(sf2) < 0) printf("bad fsync\n");
	}

	putlength(point,sf2,&sfh2);
	printf("%s\n",point);
	close(sf1); close(sf2);

	printf("\ndone.\n");
}

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