ftp.nice.ch/pub/next/unix/audio/sndutil.1.3.s.tar.gz#/sndutil-1.3/sndtools/sndtrim.c

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

/*
 * sndtrim.c
 *	Remove leading and trailing silence from a 16-bit soundfile.
 */
#import <stdio.h>
#import <sound/sound.h>
#import <math.h>

static int trace = 1;		/* for debugging */

static void fails(char *s, char *s2)
{
    printf("sndtrim: ");	/* error message  */
    printf(s,s2);
    printf("\n\n");
    exit(1);			/* error exit */
}

void main (int argc, char *argv[])
{
    int err, nchans, sampleCount, chanSamples, i;
    SNDSoundStruct *sndin, *sndout;
    FILE *outstream;
    short *data;
    double clipt;
    int startsamp=0,endsamp=0,nsamps=0;
    double thresh = 0.0;
    double attackthresh = 0.0;
    int window = 100;
    double d,ssq;
    
    while (argc> 1 && *argv[1] == '-') {
	if (*(argv[1]+1) == 't') {
	    argv++;
	    sscanf(argv[1],"%lf",&thresh);
	    printf("rms threshold set to %f\n",thresh);
	} else if (*(argv[1]+1) == 'w') {
	    argv++;
	    sscanf(argv[1],"%d",&window);
	    printf("window length set to %d\n",window);
	} else if (*(argv[1]+1) == 'a') {
	    argv++;
	    sscanf(argv[1],"%lf",&attackthresh);
	    printf("attack threshold set to %f\n",attackthresh);
	}	    
	argv++;
	argc -= 2;
    }
    
    if (argc != 3) {
	fprintf(stderr,"%s - remove leading and trailing silence from a 16-bit soundfile.\n",argv[0]);
	printf("Usage: sndtrim "
	       "[-thresh rmsFraction] "
	       "[-attackthresh rmsFraction] "
	       "[-window length] "
	       "in.snd out.snd\n");
	printf("If thresh > 0.0, trimming is outside where rms level in window"
	       " equals or exceeds the maximum amplitude times thresh.\n");
	printf("If attackthresh > 0.0, it applies to the attack while thresh "
	       "(which must also be specified) applies to the decay.\n");
	exit(1);
    }
    
    /*
     * Input sound file
     */
    err = SNDReadSoundfile(argv[1], &sndin);
    if (err) {
	fprintf(stderr, "Cannot read soundfile: %s\n", argv[1]);
	exit(1);
    }
    nchans = sndin->channelCount;
    if (sndin->dataFormat != SND_FORMAT_LINEAR_16) {
	fprintf(stderr, "Soundfile must be 16 bit linear\n");
	exit(1);
    }
    sampleCount = sndin->dataSize / sizeof(short); /* channel independent */
    chanSamples = sampleCount / nchans;	/* channel dependent count */
    data = (short *) ((char *)sndin + sndin->dataLocation);
    SNDSwapSoundToHost(data, data, chanSamples, nchans, sndin->dataFormat);
    
    /*
     * Find trim points.
     */
    
    if (thresh > 0.0) {
	double maxamp = 0;
	for (i = 0, ssq = 0.0; i < sampleCount; i++) {
	    d = abs((double)data[i]);
	    if (d>maxamp) maxamp=d;
	}
	printf("Maximum amplitude is %f out of 1.0\n",maxamp/32768.0);
	/*
	 * Clip threshold is applied to a sum of last 'window' squares.
	 */
	clipt = thresh * thresh * (double)window * maxamp * maxamp;
	/* printf("Trim threshold is %f\n",clipt); */
	
	ssq = 0.0;
	i = 0;
	for (endsamp=sampleCount-1; endsamp > startsamp; endsamp--,i++) {
	    d = (double)data[endsamp];
	    ssq += d*d;
	    if (i >= window) {
		d = (double)data[endsamp+window];
		ssq -= d*d;
	    }
	    if (ssq > clipt) {
		endsamp += window;
		if (endsamp >= sampleCount) endsamp = sampleCount-1;
		break;
	    }
	}	  

	if (attackthresh > 0.0) {
	    clipt = attackthresh * attackthresh * window * maxamp * maxamp;
	    /* printf("Attack trim threshold is %f\n",clipt); */
	}

	ssq = 0.0;
	for (startsamp = 0; startsamp < sampleCount; startsamp++) {
	    d = (double)data[startsamp];
	    ssq += d*d;
	    if (startsamp >= window) {
		d = (double)data[startsamp-window];
		ssq -= d*d;
	    }
	    if (ssq > clipt) {
		startsamp -= window;
		if (startsamp < 0) startsamp = 0;
		break;
	    }
	}	  
	
    } else {			/* zero threshold */
	for (startsamp = 0; startsamp < sampleCount; startsamp++) {
	    if (data[startsamp] > 0)
	      break;
	}
	for (endsamp=sampleCount-1; endsamp > startsamp; endsamp--) {
	    if (data[endsamp] > 0)
		break;
	}
    }
    
    nsamps=endsamp-startsamp+1,
    
    printf("Start sample is %d\n",startsamp);
    printf("End sample is %d\n",endsamp);
    
    /*
     * Output sound file
     */
    SNDAlloc(&sndout,0,SND_FORMAT_LINEAR_16,sndin->samplingRate,nchans,4);
    sndout->dataSize = nsamps;
    if (NULL == (outstream = fopen(argv[2],"w")))
      fails("could not open output file '%s'",argv[2]);
    if (trace)
      printf("Writing output file %s\n",argv[2]);
    if (SNDWriteHeader(fileno(outstream),sndout))
      fails("could not write output file '%s'",argv[2]);
    SNDSwapHostToSound(data + startsamp, data + startsamp, nsamps / nchans,
		       nchans, SND_FORMAT_LINEAR_16);
    fwrite(&data[startsamp], sizeof(short), nsamps, outstream);
    exit(0);
}

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