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

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

/* sndsynth.c - simple program shell for software sound synthesis.
   Presently configured for NeXT computers, but this can be changed by
   modifying the function writeSound().  Compile it and execute with 
   no arguments to see the usage info.
*/
   

#import <libc.h>
#import <math.h>

#define MAX_HWORD (32767.0)
#define MIN_HWORD (-32768.0)

#define DEBUG

#ifdef DEBUG
static int pof = 0;		/* positive overflow count */
static int nof = 0;		/* negative overflow count */
#endif

static inline short doubleToShort(double v)
/* v should be in [-1.0,1.0) */
{
    short out;
    v *= MAX_HWORD;
    if (v>MAX_HWORD) {
#ifdef DEBUG
	if (pof == 0)
	  fprintf(stderr, "*** sound sample overflow\n");
	else if ((pof % 10000) == 0)
	  fprintf(stderr, "*** another ten thousand overflows\n");
	pof++;
#endif
	v = MAX_HWORD;
    } else if (v < MIN_HWORD) {
#ifdef DEBUG
	if (nof == 0)
	  fprintf(stderr, "*** sound sample (-) overflow ***\n");
	else if ((nof % 1000) == 0)
	  fprintf(stderr, "*** another thousand (-) overflows **\n");
	nof++;
#endif
	v = MIN_HWORD;
    }	
    out = (short) v;
    return out;
}

/*
 * As a placeholder, we synthesize a single sinusoid 
 */

static double s_amp = 0;
static double s_ang = 0;
static double s_dang = 0;
static double s_freq = 0;
static double s_srate = 44100.0;

static void initSynth(double amplitude, double frequency, double phase)
{
    s_ang = phase*(M_PI/180.0);
    s_amp = amplitude;
    s_freq = frequency;
    s_dang = 2.0*M_PI*s_freq/s_srate;
}

static inline double nextSynthSample(void) {
    s_ang = s_ang + s_dang;
    return s_amp * sin(s_ang);
}

#import <sound/sound.h>

/* Utility for writing a mono sound to a sound file on a NeXT machine */
static int writeSound(char *name, short *soundData, int sampleCount, double fs) 
{
    int i, err;
    short *data;
    SNDSoundStruct *sound;
    SNDAlloc(&sound, sampleCount * sizeof(short), SND_FORMAT_LINEAR_16,fs,1,4);
    data = (short *) ((char *)sound + sound->dataLocation);
    for (i = 0; i < sampleCount; i++)
    	data[i] = NXSwapHostShortToBig(soundData[i]);
    err = SNDWriteSoundfile(name,sound);
    if(err)
    	fprintf(stderr,"*** Could not write sound file %s\n",name);
    else
    	printf("File %s written.\n",name);
    return err;
}

void main (int argc, char *argv[]) {
    int i, sampleCount;
    short *data;
    double amplitude, duration, pitch, phase, y;

    char *soundfile;

    if (argc != 6) {
	fprintf(stderr,"%s - simple program shell for software sound synthesis.\n",
		argv[0]);
        fprintf(stderr, "Usage: %s amp(<1.0) pitch(Hz) phase(deg) dur(sec) out.snd\n", 
		argv[0]);
        fprintf(stderr, "example:\n\t%s .5 440 0 1 out.snd\n", argv[0]);
        exit(1);
    }

    sscanf(argv[1],"%lf",&amplitude);
    sscanf(argv[2],"%lf",&pitch);
    sscanf(argv[3],"%lf",&phase);
    sscanf(argv[4],"%lf",&duration);
    soundfile = argv[5];

    sampleCount = duration * s_srate;
    data = (short *) malloc(sampleCount * sizeof(short));

    initSynth(amplitude,pitch,phase);

    for (i = 0; i < sampleCount; i++) {
        y = nextSynthSample();
        data[i] = doubleToShort(y);
    }
    
    writeSound(soundfile, data, sampleCount, s_srate);
    exit(0);
}

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