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.