This is sndproc0.c in view mode; [Download] [Up]
/* Copyright 1988-1992, NeXT Inc. All rights reserved. */ /* sndproc0.c - created from fdfilter.c (AP example) * * This program reads in a soundfile, applies a black box to * the sound, one frame at a time, and writes a new soundfile. * Currently supports only SND_FORMAT_LINEAR_16. * If the sound is multi-channel, only the first channel is filtered * and the output sound is mono. * * Usage: sndproc0 <inputSoundFile> <outputSoundFile> * * The algorithm: * You provide - currently just does a copy */ #include <stdio.h> #include <mach/mach_error.h> #include <sound/sound.h> #define FRAME_SIZE 4096 /* one page of shorts */ static void processSound(SNDSoundStruct *inputSound, SNDSoundStruct **outputSound); static void processFrame(int frameSize,short *inPtr,short *outPtr); static void convertToMono(SNDSoundStruct **theSound); static void soundErrorExit(); static void machErrorExit(); /* Static global variables */ static int soundError; /* used by soundErrorExit() macro */ static int machError; /* used by machErrorExit() macro */ static char *programName; void main(int argc, char *argv[]) { SNDSoundStruct *inputSound, *outputSound; char *inputSoundFile, *outputSoundFile; long nsamps; short *ptr; /* Check arguments */ programName = argv[0]; if (argc != 3) { fprintf(stderr, "Usage: %s <inputSoundFile> <outputSoundFile>\n", programName); exit(1); } inputSoundFile = argv[1]; outputSoundFile = argv[2]; /* Read sound file */ if (soundError = SNDReadSoundfile(inputSoundFile, &inputSound)) soundErrorExit(); /* Abort if unsupported format */ if (inputSound->dataFormat != SND_FORMAT_LINEAR_16) { fprintf(stderr, "%s: unsupported sound format: %d\n", programName, inputSound->dataFormat); exit(1); } /* convert to appropriate architecture if neccessary */ ptr = (short *) ((char *) inputSound + inputSound->dataLocation); nsamps = inputSound->dataSize / (sizeof(short) * inputSound->channelCount); SNDSwapSoundToHost(ptr, ptr, nsamps, inputSound->channelCount, inputSound->dataFormat); /* Convert to mono if required */ if (inputSound->channelCount > 1) { fprintf(stderr, "%s: Warning: averaging channels " "of a %d-channel sound\n", programName,inputSound->channelCount); convertToMono(&inputSound); } /* Filter by applying window in the frequency domain */ processSound(inputSound, &outputSound); /* convert the sound ready to write out */ ptr = (short *) ((char *) outputSound + outputSound->dataLocation); nsamps = outputSound->dataSize / (sizeof(short)*outputSound->channelCount); SNDSwapHostToSound(ptr, ptr, nsamps, outputSound->channelCount, outputSound->dataFormat); /* Write sound file */ if (soundError = SNDWriteSoundfile(outputSoundFile, outputSound)) soundErrorExit(); } /* * processSound * Apply a "black box" to the input sound * in the frequency domain and write results to the output sound. */ static void processSound(SNDSoundStruct *inputSound, SNDSoundStruct **outputSound) { int size = inputSound->dataSize; int format = inputSound->dataFormat; int rate = inputSound->samplingRate; int channels = inputSound->channelCount; short *inPtr, *outPtr, *inFramePtr, *outFramePtr, *frameBuffer; int numFrames, frameSize, sizeDone=0; /* Allocate a new sound (uses vm_allocate() => data is pre-zeroed) */ if (soundError = SNDAlloc(outputSound, size, format, rate, channels, 4)) soundErrorExit(); size /= sizeof(short); inPtr = (short *) ((char *) inputSound + inputSound->dataLocation); outPtr = (short *) ((char *) *outputSound + (*outputSound)->dataLocation); /* Use vm_allocate() to get page alignment */ machError = vm_allocate(task_self(), (pointer_t *)&frameBuffer, FRAME_SIZE * sizeof(short),1); if (machError != KERN_SUCCESS) machErrorExit(); numFrames = (size + FRAME_SIZE - 1) / FRAME_SIZE; /* For each frame, download, filter, upload, and overlap-add into output */ for (sizeDone=0, inFramePtr=inPtr, outFramePtr=outPtr; sizeDone < size; sizeDone+=FRAME_SIZE, inFramePtr+=FRAME_SIZE, outFramePtr+=FRAME_SIZE) { frameSize = (FRAME_SIZE < (size-sizeDone)? FRAME_SIZE : size-sizeDone); processFrame(frameSize,inFramePtr,outFramePtr); } /* All sound signals should start and end at 0 amp to avoid driver ramp */ *outPtr = *(outPtr+size-1) = 0; } /* * processFrame */ static void processFrame(int frameSize,short *inPtr,short *outPtr) { int i; for (i=0; i<frameSize; i++) *outPtr++ = *inPtr++; /* copy */ } /* Convert multi-channel sound to mono by tossing extra channels */ static void convertToMono(SNDSoundStruct **theSound) { SNDSoundStruct *newSound; short *oldPtr, *newPtr; int size = (*theSound)->dataSize; int format = (*theSound)->dataFormat; int rate = (*theSound)->samplingRate; int channels = (*theSound)->channelCount; int newSize, i, j, k, s, scl; newSize = size/channels; if (soundError = SNDAlloc(&newSound, newSize, format, rate, 1, 4)) soundErrorExit(); oldPtr = (short *) ((char *) *theSound + (*theSound)->dataLocation); newPtr = (short *) ((char *) newSound + newSound->dataLocation); #define SCALE_BITS 10 scl = (1<<SCALE_BITS)/channels; for (i = 0, j = 0; i < newSize/sizeof(short); i++, j+=channels) { for (k=0, s=0; k<channels; k++) s += (int)oldPtr[j+k]; s *= scl; newPtr[i] = s >> SCALE_BITS; } if (soundError = SNDFree(*theSound)) soundErrorExit(); *theSound = newSound; } /* Sound error handling macro */ void soundErrorExit() { fprintf(stderr, "%s: sound error: %s\n", programName, SNDSoundError(soundError)); exit(1); } /* Mach error handling macro */ void machErrorExit() { fprintf(stderr, "%s: mach error: %s\n", programName, mach_error_string(machError)); exit(1); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.