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,&c)) { 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.