ftp.nice.ch/pub/next/unix/audio/fugue.s.tar.gz#/fugue/table.c

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

/*
 * FILE: extras.c
 *   BY: George Polly
 * DESC: additons to the fugue library, including oscillators and filters
 *
 * 1.0 (26-APR-89) - created. (clf)
 */


#include <math.h>
#include "xlisp.h"
#include "sound.h"
#include "fugue.h"

float s_maxSample();

SoundPtr xform(table, y)
SoundPtr table, y;
{
   SoundPtr s;
   SDataPtr data;
   int len, tableLen;
   double d;
   int i;

   (void)s_flatten(y);
   (void)s_flatten(table);
   s = s_create();
   len = y->ptr.sample->length;
   data = sdata_create(len);
   s->ptr.sample = spl_create(data, len, y->srate);
   s->tag = SAMPLES;
   s->to = s->logicalTo = len / y->srate;
   s->srate = y->srate;
   s->shift = y->shift;
   tableLen = table->ptr.sample->length;
   for (i = 1; i <= len; i++)
     {
     d = y->ptr.sample->data[i];
     d -= floor(d);
     if (d < 0.0)
        d += 1;
     s->ptr.sample->data[i] = *(table->ptr.sample->data + 1 +
				(int)(tableLen * d));
     }
   return (s);
}



/* This routine performs an AM oscillator on the given sounds. 'Key' is the key
  of the passed 's2', 'srate' is the desired sampling rate, 'pitch' is
  the desired pitch, 'phase' is the starting phase, and 'oneshot' is a
  flag which when one performs only 1 pass of the oscillator. 'S2' is the
  carrier and 's1' is the modulator. */

SoundPtr s_amosc(s2, key, srate, pitch, s1, phase, one_shot)
SoundPtr s2;
double key, srate, pitch;
SoundPtr s1;
double phase;
int one_shot;
{
    SDataPtr s1_start, s2_start;	/* sound starts in mem */
    SoundPtr new_so;			/* the newly create sound */
    SDataPtr s1_ptr, sf_ptr;		/* ptr to current loc */
    SDataPtr s1_end, s2_end;		/* end of sound data */
    long s1_len, s2_len, sf_len;	/* length of sounds */
    double d, f;			/* interpolation vars */
    double step;			/* amt to step through s1 */
    double s2_ptr;			/* pointer to current loc */

    new_so = s_create();
    s_flatten(s1);			/* get rid of any laziness */
    s_flatten(s2);

    step = (pitch * s2->srate) / (srate * step_to_hz(key) );
                                        /* step rate for pitch */

    s1_start = s1->ptr.sample->data;	/* init pointers */
    s2_start = s2->ptr.sample->data;
    s1_len = s1->ptr.sample->length;
    s2_len = s2->ptr.sample->length;

    if (s2_len >= s1_len)		/* one shot if we must */
	one_shot = 1;

    sf_len = s1_len;
    s1_end = s1_start +	s1_len;		/* set lengths */
    s2_end = s2_start + s2_len;

    sf_ptr = sdata_create(sf_len);	/* get room for sound */

    new_so->from    = 0.0;		/* init our new sound */
    new_so->to	    = new_so->logicalTo = sf_len/srate;
    new_so->stretch = 1.0;
    new_so->srate   = srate;
    new_so->tag	    = SAMPLES;
    new_so->ptr.sample = spl_create(sf_ptr, sf_len, srate);

    s1_ptr = s1_start;			/* init pointers for start */
    s2_ptr = s2_len * key * (phase / (double) ANGLEBASE);

    while (s1_ptr < s1_end)		/* for whole modulator */
	{

	while ( (s1_ptr < (s1_end - sizeof(s1_ptr) )) && (s2_ptr < (s2_len - step)))
	    {				/* for each cycle of carrier */
	    d = s2_ptr - floor(s2_ptr);
	    f = 1.0 -d;			/* interpolate */
	    *(sf_ptr++) = *(s1_ptr++)  * (f * ( *(s2_start + (int) s2_ptr)) +
				d * (  *(s2_start + (int) (s2_ptr + step))));
	    s2_ptr += step;
	    }
	    
	if  (one_shot)
	    break;

	d = s2_ptr - floor(s2_ptr);
	f = 1.0	-d;			/* interpolate */
	*(sf_ptr++) = *(s1_ptr++) * (f * ( *(s2_start + (int) s2_ptr))
	                             + d * ( *(s2_start)));
	s2_ptr = 0;			/* reset carrier */
	}

    return (new_so);			/* give back new sound */
}



/* This routine performs an FM oscillator on the given sounds. 'Key' is the key
  of the passed 's2', 'srate' is the desired sampling rate, 'pitch' is
  the desired pitch, 'phase' is the starting phase, and 'oneshot' is a
  flag which when one performs only 1 pass of the oscillator. 'S2' is the
  carrier and 's1' is the modulator. */

SoundPtr s_fmosc(ca, key, srate, freq, mo, phase, one_shot)
  SoundPtr ca;  /* the carrier wavetable */
  double key;   /* the carrier pitch */
  double srate; /* sample rate of result */
  double freq; /* frequency offset of result */
  SoundPtr mo;  /* the modulator */
  double phase; /* initial phase of carrier */
  int one_shot; /* loop through table? */
{
    SDataPtr mo_start, ca_start;    /* sound starts in mem */
    SoundPtr new_so;		    /* the newly create sound */
    SDataPtr mo_ptr;
    SDataPtr new_ptr;		    /* ptr to current loc */
    SDataPtr mo_end, ca_end;	    /* end of sound data */
    long ca_len, mo_len, new_len;   /* length of sounds */
    double mo_dt;		    /* modulator resample increment */
    double d, f;		    /* interpolation vars */
    double dtbase;		    /* carrier baseline phase increment */
    double dt;		   	    /* phase increment due to modulation */
    double ca_phase, mo_phase;	    /* current phase for carrier and modul. */
    long fp;                        /* integer part of phase */
    double mo_scale;		    /* multiply by mo to get delta phase */
    int valid;                      /* see if signals have extent */
    double minimum, maximum;        /* extent of signals */

    new_so = s_create();		/* get rid of laziness */
    s_flatten(ca);
    valid = extent(ca, &minimum, &maximum);
    if (!valid) return s_silence(new_so);    
    ca_start = locate_sample(ca, minimum);
    ca_len = (long) ((maximum - minimum) * ca->srate + 0.5);
    ca_end = ca_start + ca_len;
    ca_phase = compute_phase(phase, key, ca_len, ca->srate, srate, 
			     freq, &dtbase);

    s_flatten(mo);
    valid = extent(mo, &minimum, &maximum);
    if (!valid) return s_silence(new_so);
    mo_start = locate_sample(mo, minimum);
    mo_len = (maximum - minimum) * mo->srate + 0.5;
    mo_end = mo_start + mo_len;
    mo_phase = 0;
    mo_dt = mo->srate / srate;	
    /* want to figure factor between mo (in hz) and delta phase for carrier
	dtbase represents the delta used to get step_to_hz(pitch), so 1 hz
	deviation takes dtbase / freq;
     */
    mo_scale = dtbase / freq;

    new_len = (maximum - minimum) * srate + 0.5;
    new_ptr = sdata_create(new_len);
    new_so->ptr.sample = spl_create(new_ptr, new_len, srate);
    new_so->from = 0.0;		/* init new sound */
    new_so->to = new_so->logicalTo = mo->logicalTo;
    new_so->stretch = 1.0;
    new_so->srate   = srate;
    new_so->tag	    = SAMPLES;
	
/*printf("mo_ptr = %d  mo_end = %d ca_len = %d ", mo_ptr, mo_end, ca_len);
printf ("ca_phase = %f dt2 =  %f dtbase = %f\n", ca_phase, dt2, dtbase);*/
/* NOTE: Don't interpolate for now */

    while (new_len--) {
        /* if frequency modulation really gets out of hand this while
	   might actually loop, otherwise it could be an "if" */
	while (ca_phase >= ca_len) ca_phase -= ca_len;
	fp = floor(ca_phase);
	d = ca_phase - fp;
	f = 1.0 - d;
	*new_ptr++ = (f * ca_start[fp]) +
	    d * (fp + 1 == ca_len ? (*ca_start) : ca_start[fp + 1]);
	/* now compute new phase, don't interpolate modulation */
	dt = dtbase + (mo_scale * mo_start[(long) floor(mo_phase)]);
	mo_phase += mo_dt;
	if (dt < 0.0) dt = 0.0;  /* clip to avoid negative frequency */
	ca_phase += dt;
    }
    return new_so;
}



/* This is a first order Butterworth lowpass filter routine, where 's is the
  sound and 'f' is the cutoff frequency */

SoundPtr s_lp(s, f)
SoundPtr s;
double f;
{
    SDataPtr s_start;			/* start of sample data */
    long s_len;				/* length of sample in samples */
    long n;				/* number into sample */
    SoundPtr new_so;			/* ptr to filtered sound  block*/
    SDataPtr sf_start;			/* ptr to filtered sound start */
    double c1, c2;			/* difference eq constants */

    new_so = s_create();
    s_flatten(s);			/* get rid of laziness */

    s_start  = s->ptr.sample->data;	/* point to sound */
    s_len    = s->ptr.sample->length;

    sf_start = sdata_create(s_len);	/* make new sound */

    new_so->from    = 0.0;		/* init our new sound */
    new_so->to	    = new_so->logicalTo = s_len / s->srate;
    new_so->stretch = 1.0;
    new_so->srate   =  s->srate;
    new_so->tag	    = SAMPLES;
    new_so->ptr.sample = spl_create(sf_start, s_len, s->srate);

    c1 = 2.0 * 3.1415 * f;
    c2 = exp( - c1 /  (double) s->srate );

    sf_start[0]	= c1 * s_start[0];	/* do it */
    for (n= 1; n < s_len; ++n)
	sf_start[n] = c1 * s_start[n] + c2 * sf_start[n-1];

    return(new_so);
}



/* This is a first order Butterworth varaible highpass filter routine, where
  's' is the sound, 'f' is a sound containing the cutoff frequencies, and
  'm' is the size of the cut.*/

SoundPtr s_lp_var(s, f, m)
SoundPtr s, f;
double m;
{
    SDataPtr s_start, f_ptr;		/* start of sample data */
    SDataPtr s_end, sp_end;		/* end of sample data */
    long s_len, f_len;			/* length of sample in samples */
    long n;				/* number into sample */
    SoundPtr new_so;			/* ptr to filtered sound  block*/
    SDataPtr sf_start;			/* ptr to filtered sound start */
    double c1, c2, df;			/* difference eq constants */
    SDataType freq;			/* frequency of filter */

    new_so = s_create();		/* create new sound */
    s_flatten(s);			/* get rid of lziness */

    s_start = s->ptr.sample->data;	/* find the pointers we need */
    f_ptr   = f->ptr.sample->data;
    s_len   = s->ptr.sample->length;
    f_len   = f->ptr.sample->length;
    s_end   = s_start + s_len;
    sf_start = sdata_create(s_len);

    new_so->from    = 0.0;		/* init new sound */
    new_so->to	    = new_so->logicalTo = s_len / s->srate;
    new_so->stretch = 1.0;
    new_so->srate   =  s->srate;
    new_so->tag	    = SAMPLES;
    new_so->ptr.sample = spl_create(sf_start, s_len, s->srate);

    df = ( (double) f_len / (double) s_len) * sizeof( *f_ptr )  *  m;
    sp_end = s_start + (int) m;
    sf_start[0] = c1 * s_start[0];
    n = 1;

    while ( &s_start[n]	< s_end)    /* for each part of the freq wave */
	{
	freq = *f_ptr;
	f_ptr +=  (int) df;
	c1 = 2.0 * 3.1415 * freq;
	c2 = exp( - c1 /  (double) s->srate );

	while ((&s_start[n] < s_end) && (&s_start[n] < sp_end))
		{		    /* for each segment of sound */

		sf_start[n] = c1 * s_start[n] + c2 * sf_start[n -1];
		n++;
		}

	sp_end += (int) m;
	}

    return(new_so);
}



/* This is a first order Butterworth highpass filter routine, where 's' is the
  sound and 'f' is the cutoff frequency */

SoundPtr s_hp(s, f)
SoundPtr s;
double f;
{
    SDataPtr s_start;			/* start of sample data */
    long s_len;				/* length of sample in samples */
    long n;				/* number into sample */
    SoundPtr new_so;			/* ptr to filtered sound  block*/
    SDataPtr sf_start;			/* ptr to filtered sound start */
    double c1, c2;			/* difference eq constants */

    new_so = s_create();
    s_flatten(s);			/* get rid of laziness */

    s_start  = s->ptr.sample->data;	/* point to sound */
    s_len    = s->ptr.sample->length;

    sf_start = sdata_create(s_len);	/* make new sound */

    new_so->from    = 0.0;		/* init our new sound */
    new_so->to	    = new_so->logicalTo = s_len / s->srate;
    new_so->stretch = 1.0;
    new_so->srate   =  s->srate;
    new_so->tag	    = SAMPLES;
    new_so->ptr.sample = spl_create(sf_start, s_len, s->srate);

    c1 = 2.0 * 3.1415 * f;
    c2 = exp( - c1 /  (double) s->srate );

    sf_start[0] = c2 * s_start[0];
    for (n= 1; n < s_len; ++n)
	sf_start[n] = c2 * ((sf_start[n-1] - s_start[n-1]) + s_start[n]);

    return(new_so);
}



/* This is a first order Butterworth varaible highpass filter routine, where
  's' is the sound, 'f' is a sound containing the cutoff frequencies, and
  'm' is the size of the cut.*/

SoundPtr s_hp_var(s, f, m)
SoundPtr s, f;
double m;
{
    SDataPtr s_start, f_ptr;		/* start of sample data */
    SDataPtr s_end, sp_end;		/* end of sample data */
    long s_len, f_len;			/* length of sample in samples */
    long n;				/* number into sample */
    SoundPtr new_so;			/* ptr to filtered sound  block*/
    SDataPtr sf_start;			/* ptr to filtered sound start */
    double c1, c2, df;			/* difference eq constants */
    SDataType freq;			/* frequency of filter */

    new_so = s_create();		/* create new sound */
    s_flatten(s);			/* get rid of lziness */

    s_start = s->ptr.sample->data;	/* find the pointers we need */
    f_ptr   = f->ptr.sample->data;
    s_len   = s->ptr.sample->length;
    f_len   = f->ptr.sample->length;
    s_end   = s_start + s_len;
    sf_start = sdata_create(s_len);

    new_so->from    = 0.0;		/* init new sound */
    new_so->to	    = new_so->logicalTo = s_len / s->srate;
    new_so->stretch = 1.0;
    new_so->srate   =  s->srate;
    new_so->tag	    = SAMPLES;
    new_so->ptr.sample = spl_create(sf_start, s_len, s->srate);

    df = ( (double) f_len / (double) s_len) * sizeof( *f_ptr );
    sp_end = s_start + (int) m;
    c1 = 2.0 * 3.1415 * (*f_ptr);
    c2 = exp( - c1 /  (double) s->srate );
    sf_start[0] = c2 * s_start[0];
    n = 1;

    while ( &s_start[n]	< s_end)	    /* for each part of freq wave */
	{
	freq = *f_ptr;
	f_ptr+=  (int) df;
	c1 = 2.0 * 3.1415 * freq;
	c2 = exp( - c1 /  (double) s->srate );

	while ((&s_start[n] < s_end) && (&s_start[n] < sp_end))
		{			    /* for each seg of sound */

		sf_start[n] = c2 * ((sf_start[n -1] - s_start[n -1]) + s_start[n]);
		n++;
		}

	sp_end += (int) m;
	}

    return(new_so);
}



/* This is a first order Butterworth bandpass filter routine, where 's' is the
  sound and 'f_l' is the low cutoff frequency and 'f_h' is the high cutoff
  frequency */

SoundPtr s_bp(s, f_l, f_h)
SoundPtr s;
double f_l, f_h;
{
    double f_c;			    /* band width of freq */
    SDataPtr s_start;		    /* start of sample data */
    long s_len;			    /* length of sample in samples */
    long n;			    /* number into sample */
    SoundPtr new_so;		    /* ptr to filtered sound  block*/
    SDataPtr sf_start;		    /* ptr to filtered sound start */
    double c1, c2, c3, c4;	    /* difference eq constants */
    double w_h,	w_l, a,	b, k, t;    /* other constants */

    new_so = s_create();		/* create new sound */
    s_flatten(s);			/* get rid of our laziness */

    s_start = s->ptr.sample->data;	/* ptrs at sound */
    s_len   = s->ptr.sample->length;
    sf_start = sdata_create(s_len);

    new_so->from    = 0.0;		/* init new sound */
    new_so->to	    = new_so->logicalTo = s_len / s->srate;
    new_so->stretch = 1.0;
    new_so->srate   = s->srate;
    new_so->tag	    = SAMPLES;
    new_so->ptr.sample = spl_create(sf_start, s_len, s->srate);

    w_h	= 2.0 *	3.1415 * f_h;		/* yuck! */
    w_l = 2.0 * 3.1415 * f_l;
    t = 1.0 / (double) s->srate;
    c1 = (w_h - w_l) * t / 2.0;
    c2 = (w_h + w_l) * t / 2.0;
    k = tan( ((f_h - f_l)/2 + f_l) * 2 * 3.1415) / tan( c1 );
    a = cos( c2 ) / cos( c1 );
    a = (-2.0 * a * k)/(k + 1);
    b = (k - 1) / (k + 1);

    c1 = (1 - b)/(3 + b);
    c2 = - c1;
    c3 = (2 * a)/(3 + b);
    c4 = (1 + 3*b)/(3+b);
    printf("%f %f %f %f", c1, c2, c3, c4);

    sf_start[0] = c1*s_start[0];
    sf_start[1] = c1*s_start[1] + c3*sf_start[0];
    for (n = 2; n < s_len; ++n)
        sf_start[n] =  c1*s_start[n]  + c2*s_start[n-2] 
                         + c3*sf_start[n-1] + c4*sf_start[n-2];

    return(new_so);
}



/* This is a first order Butterworth varaible highpass filter routine, where
  's' is the sound, 'f' is a sound containing the cutoff frequencies, and
  'm' is the size of the cut.*/
/* NOTE: WAITING FOR CORRECT BANDPASS FILTER FORMULA */

SoundPtr s_bp_var(s, f, f_w, m)
SoundPtr s, f;
double m;
{
    SDataPtr s_start, f_ptr;		/* start of sample data */
    SDataPtr s_end, sp_end;		/* end of sample data */
    long s_len, f_len;			/* length of sample in samples */
    long n;				/* number into sample */
    SoundPtr new_so;			/* ptr to filtered sound  block*/
    SDataPtr sf_start;			/* ptr to filtered sound start */
    double c1, c2, c3, c4, x;		/* difference eq constants */
    double w_c, f_c, df, freq;		/* frequency variables */

    new_so = s_create();		/* new sound */
    s_flatten(s);			/* x the laxy stuff */

    s_start = s->ptr.sample->data;	/* find the things */
    f_ptr   = f->ptr.sample->data;
    s_len   = s->ptr.sample->length;
    f_len   = f->ptr.sample->length;
    s_end   = s_start + s_len;
    sf_start = sdata_create(s_len);

    new_so->from    = 0.0;		/* init new sound */
    new_so->to	    = new_so->logicalTo = s_len / s->srate;
    new_so->stretch = 1.0;
    new_so->srate   = s->srate;
    new_so->tag	    = SAMPLES;
    new_so->ptr.sample = spl_create(sf_start, s_len, s->srate);

/*    df = f_len / s_len;
    sp_end = s_start + (int) m;
    c1 = w_c = 2.0 * 3.1415 * f_c;
    x = (2.0* 3.1415 * f_h * 2.0 * 3.1415 * f_l) - ( w_c * w_c / 4.0 );
    c2 = - w_c * exp( - ( w_c /  (double) s->srate * 2.0) ) * (cos(x) + sin(x))
                                / (double) s->srate;
    c3 = 2.0 * exp( - (w_c / (double) s->srate * 2.0)) * cos(x);
    c4 = - exp( -w_c / (double) s->srate);

    sf_start[0] = c1 * s_start[0];
    n = 2;

    while ( &s_start[n] < s_end)
	{
	freq = *f_ptr;
	f_ptr+=  (int) df;
	c1 = w_c = 2.0 * 3.1415 * f_c;
	x = (2.0* 3.1415 * f_h * 2.0 * 3.1415 * f_l) - ( w_c * w_c / 4.0 );
	c2 = - w_c * exp( - ( w_c /  (double) s->srate * 2.0) ) * (cos(x) + sin(x))
                                / (double) s->srate;
	c3 = 2.0 * exp( - (w_c / (double) s->srate * 2.0)) * cos(x);
	c4 = - exp( -w_c / (double) s->srate);

	while ((&s_start[n] < s_end) && (&s_start[n] < sp_end))
		{
	        sf_start[n] = c1 * s_start[n] + c2 * s_start[n -1] 
                                	+ c3 * sf_start[n -1] + c4 * sf_start[n - 2];
		n++;
		}
	sp_end += (int) m;
	}*/

    return(new_so);
}



/* This function implements a white noise algorithm for 'dur' seconds at
    a sampling rate of 'srate'. */

SoundPtr s_white_noise(dur, srate)
double dur, srate;
{
    SDataPtr s_start;			/* start of sample data */
    SDataPtr s_end;			/* end of sample data */
    long s_len;				/* length of sample in samples */
    SoundPtr new_so;			/* ptr to filtered sound  block*/
    double m;				/* scalar factor for random */

    new_so  = s_create();		/* create a sound */
    s_len   = dur * srate;
    s_start = sdata_create(s_len);
    s_end   = s_start + s_len;

    new_so->from    = 0.0;		/* initialize the sound */
    new_so->to	    = new_so->logicalTo = s_len / srate;
    new_so->stretch = 1.0;
    new_so->srate   =  srate;
    new_so->tag	    = SAMPLES;
    new_so->ptr.sample = spl_create(s_start, s_len, srate);

    m =	32767.0	/  ( pow(2, 31)	- 1);	/* create using random */
    while ( s_start < s_end)
	*(s_start++) = random() * m;

    return(new_so);
}

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