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.