/*
 * Prepare for processing.
 */
int st_earwax_start(eff_t effp)
{
  earwax_t earwax = (earwax_t) effp->priv;
  int i;

  /* check the input format */
  if (effp->ininfo.encoding != ST_ENCODING_SIGN2
      || effp->ininfo.rate != 44100
      || effp->ininfo.channels != 2){
    st_fail("the earwax effect works only with audio cd (44.1 kHz, twos-complement signed linear, stereo) samples.\n");
    return (ST_EOF);
  }

  /* allocate tap memory */
  earwax->tap = (st_sample_t*)malloc( sizeof(st_sample_t) * EARWAX_NUMTAPS );
  if( !earwax->tap ){
    st_fail("earwax: Cannot malloc %d bytes!\n", 
	    sizeof(st_sample_t) * EARWAX_NUMTAPS );
    return (ST_EOF);
  }

  /* zero out the delayed taps */
  for(i=0; i < EARWAX_NUMTAPS; i++ ){
    earwax->tap[i] = 0;
  }

  return (ST_SUCCESS);
}
/*
 * Start processing
 */
int st_trim_start(eff_t effp)
{
    trim_t trim = (trim_t) effp->priv;

    if (st_parsesamples(effp->ininfo.rate, trim->start_str,
                        &trim->start, 't') != ST_SUCCESS)
    {
        st_fail(TRIM_USAGE);
        return(ST_EOF);
    }
    /* Account for # of channels */
    trim->start *= effp->ininfo.channels;

    if (trim->length_str)
    {
        if (st_parsesamples(effp->ininfo.rate, trim->length_str,
                    &trim->length, 't') != ST_SUCCESS)
        {
            st_fail(TRIM_USAGE);
            return(ST_EOF);
        }
    }
    else
        trim->length = 0;

    /* Account for # of channels */
    trim->length *= effp->ininfo.channels;

    trim->index = 0;
    trim->trimmed = 0;

    return (ST_SUCCESS);
}
/*
 * Process options: gain (float) type (amplitude, power, dB)
 */
int st_vol_getopts(eff_t effp, int n, char **argv) 
{
    vol_t vol = (vol_t) effp->priv; 
    vol->gain = ONE; /* default is no change */
    vol->uselimiter = 0; /* default is no limiter */
    
    if (n && (!sscanf(argv[0], VOL_FLOAT_SCAN, &vol->gain)))
    {
        st_fail(VOL_USAGE);
        return ST_EOF;
    }

    /* adjust gain depending on type (what a great parser;-) */
    if (n>1) 
    {
        switch (argv[1][0]) 
        {
        case 'd': /* decibels to amplitude */
        case 'D':
            vol->gain = exp(vol->gain*LOG_10_20);
            break;
        case 'p':
        case 'P': /* power to amplitude, keep phase change */
            if (vol->gain > ZERO)
                vol->gain = sqrt(vol->gain);
            else
                vol->gain = -sqrt(-vol->gain);
            break;
        case 'a': /* amplitude */
        case 'A':
        default:
            break;
        }
    }
    

    if (n>2)
    {
        if ((fabs(vol->gain) < ONE) || !sscanf(argv[2], VOL_FLOAT_SCAN, &vol->limitergain) || !((vol->limitergain > ZERO) && (vol->limitergain < ONE)))
        {
                st_fail(VOL_USAGE);
                return ST_EOF;                  
        }
        
        vol->uselimiter = 1; /* ok, we'll use it */
        /* The following equation is derived so that there is no 
         * discontinuity in output amplitudes */
        /* and a ST_SAMPLE_MAX input always maps to a ST_SAMPLE_MAX output 
         * when the limiter is activated. */
        /* (NOTE: There **WILL** be a discontinuity in the slope 
         * of the output amplitudes when using the limiter.) */
        vol->limiterthreshhold = ST_SAMPLE_MAX * (ONE - vol->limitergain) / (fabs(vol->gain) - vol->limitergain);
    }
    

    return ST_SUCCESS;
}
/*
 * Prepare processing.
 * Do all initializations.
 */
int st_noisered_start(eff_t effp)
{
    reddata_t data = (reddata_t) effp->priv;
    int fchannels = 0;
    int channels = effp->ininfo.channels;
    int i;
    FILE* ifd;

    data->chandata = (chandata_t*)calloc(channels, sizeof(*(data->chandata)));
    for (i = 0; i < channels; i ++) {
        data->chandata[i].noisegate = (float*)calloc(FREQCOUNT, sizeof(float));
        data->chandata[i].smoothing = (float*)calloc(FREQCOUNT, sizeof(float));
        data->chandata[i].lastwindow = NULL;
    }
    data->bufdata = 0;

    /* Here we actually open the input file. */
    ifd = fopen(data->profile_filename, "r");
    if (ifd == NULL) {
        st_fail("Couldn't open profile file %s: %s",
                data->profile_filename, strerror(errno));            
        return ST_EOF;
    }

    while (1) {
        int i1;
        float f1;
        if (2 != fscanf(ifd, " Channel %d: %f", &i1, &f1))
            break;
        if (i1 != fchannels) {
            st_fail("noisered: Got channel %d, expected channel %d.",
                    i1, fchannels);
            return ST_EOF;
        }

        data->chandata[fchannels].noisegate[0] = f1;
        for (i = 1; i < FREQCOUNT; i ++) {
            if (1 != fscanf(ifd, ", %f", &f1)) {
                st_fail("noisered: Not enough datums for channel %d "
                        "(expected %d, got %d)", fchannels, FREQCOUNT, i);
                return ST_EOF;
            }
            data->chandata[fchannels].noisegate[i] = f1;
        }
        fchannels ++;
    }
    if (fchannels != channels) {
        st_fail("noisered: channel mismatch: %d in input, %d in profile.\n",
                channels, fchannels);
        return ST_EOF;
    }
    fclose(ifd);

    return (ST_SUCCESS);
}
/*
 * Process options
 */
int st_stat_getopts(eff_t effp, int n, char **argv)
{
        stat_t stat = (stat_t) effp->priv;

        stat->scale = ST_SAMPLE_MAX;
        stat->volume = 0;
        stat->srms = 0;
        stat->fft = 0;

        while (n>0)
        {
                if (!(strcmp(argv[0], "-v")))
                {
                        stat->volume = 1;
                }
                else if (!(strcmp(argv[0], "-s")))
                {
                        double scale;

                        if (n <= 1)
                        {
                          st_fail("-s option: invalid argument");
                          return (ST_EOF);
                        }
                        if (!sscanf(argv[1], "%lf", &scale))
                        {
                          st_fail("-s option: invalid argument");
                          return (ST_EOF);
                        }
                        stat->scale = scale;

                        /* Two option argument.  Account for this */
                        --n; ++argv;
                }
                else if (!(strcmp(argv[0], "-rms")))
                {
                        stat->srms = 1;
                }
                else if (!(strcmp(argv[0], "-freq")))
                {
                        stat->fft = 1;
                }
                else if (!(strcmp(argv[0], "-d"))) {
                        stat->volume = 2;
                }
                else
                {
                        st_fail("Summary effect: unknown option");
                        return(ST_EOF);
                }
                --n; ++argv;
        }
        return (ST_SUCCESS);
}
/*
 * Process options
 */
int st_resample_getopts(eff_t effp, int n, char **argv) 
{
	resample_t r = (resample_t) effp->priv;

	/* These defaults are conservative with respect to aliasing. */
	r->rolloff = 0.80;
	r->beta = 16; /* anything <=2 means Nutall window */
	r->quadr = 0;
	r->Nmult = 45;

	/* This used to fail, but with sox-12.15 it works. AW */
	if ((n >= 1)) {
		if (!strcmp(argv[0], "-qs")) {
			r->quadr = 1;
			n--; argv++;
		}
		else if (!strcmp(argv[0], "-q")) {
			r->rolloff = 0.875;
			r->quadr = 1;
			r->Nmult = 75;
			n--; argv++;
		}
		else if (!strcmp(argv[0], "-ql")) {
			r->rolloff = 0.94;
			r->quadr = 1;
			r->Nmult = 149;
			n--; argv++;
		}
	}

	if ((n >= 1) && (sscanf(argv[0], "%lf", &r->rolloff) != 1))
	{
	  st_fail("Usage: resample [ rolloff [ beta ] ]");
	  return (ST_EOF);
	}
	else if ((r->rolloff <= 0.01) || (r->rolloff >= 1.0))
	{
	  st_fail("resample: rolloff factor (%f) no good, should be 0.01<x<1.0", r->rolloff);
	  return(ST_EOF);
	}

	if ((n >= 2) && !sscanf(argv[1], "%lf", &r->beta))
	{
	  st_fail("Usage: resample [ rolloff [ beta ] ]");
	  return (ST_EOF);
	}
	else if (r->beta <= 2.0) {
	  r->beta = 0;
		st_report("resample opts: Nuttall window, cutoff %f\n", r->rolloff);
	} else {
		st_report("resample opts: Kaiser window, cutoff %f, beta %f\n", r->rolloff, r->beta);
	}
	return (ST_SUCCESS);
}
/*
 * Prepare processing.
 */
int st_stat_start(eff_t effp)
{
        stat_t stat = (stat_t) effp->priv;
        int i;
        unsigned long  bitmask;

        stat->min = stat->max = stat->mid = 0;
        stat->asum = 0;
        stat->sum1 = stat->sum2 = 0;

        stat->dmin = stat->dmax = 0;
        stat->dsum1 = stat->dsum2 = 0;

        stat->last = 0;
        stat->read = 0;

        for (i = 0; i < 4; i++)
                stat->bin[i] = 0;

        stat->fft_size = 4096;
        stat->re = 0;
        stat->im = 0;

        if (stat->fft)
        {
            bitmask = 0x80000000L;
            stat->fft_bits = 31;
            stat->fft_offset = 0;
            while (bitmask && !(stat->fft_size & bitmask))
            {
                bitmask = bitmask >> 1;
                stat->fft_bits--;
            }

            if (bitmask && (stat->fft_size & ~bitmask))
            {
                st_fail("FFT can only use sample buffers of 2^n. Buffer size used is %ld\n",stat->fft_size);
                return(ST_EOF);
            }

            stat->re = (double *)malloc(sizeof(double) * stat->fft_size);
            stat->im = (double *)malloc(sizeof(double) * stat->fft_size);

            if (!stat->re || !stat->im)
            {
                st_fail("Unable to allocate memory for FFT buffers.\n");
                return (ST_EOF);
            }
        }
static int parse_subarg(char *s, char **subargv, int *subargc) {
  char **ap;
  char *s_p;

  s_p = s;
  *subargc = 0;
  for (ap = subargv; (*ap = strtok(s_p, " \t")) != NULL;) {
    s_p = NULL;
    if (*subargc == 5) {
      ++*subargc;
      break;
    }
    if (**ap != '\0') {
      ++ap;
      ++*subargc;
    }
  }

  if (*subargc < 2 || *subargc > 5)
    {
      st_fail("Wrong number of arguments for the compander effect within mcompand\n"
           "Use: {<attack_time>,<decay_time>}+ {<dB_in>,<db_out>}+ "
           "[<dB_postamp> [<initial-volume> [<delay_time]]]\n"
           "where {}+ means `one or more in a comma-separated, "
           "white-space-free list'\n"
           "and [] indications possible omission.  dB values are floating\n"
           "point or `-inf'; times are in seconds.");
      return (ST_EOF);
    } else
      return ST_SUCCESS;
}
/*
 * Process options
 *
 * Don't do initialization now.
 * The 'info' fields are not yet filled in.
 */
int st_swap_getopts(eff_t effp, int n, char **argv) 
{
    swap_t swap = (swap_t) effp->priv;

    swap->order[0] = swap->order[1] = swap->order[2] = swap->order[3] = 0;
    if (n)
    {
        swap->def_opts = 0;
        if (n != 2 && n != 4)
        {
            st_fail("Usage: swap [1 2 | 1 2 3 4]");
            return (ST_EOF);
        }
        else if (n == 2)
        {
            sscanf(argv[0],"%d",&swap->order[0]);
            sscanf(argv[1],"%d",&swap->order[1]);
        }
        else
        {
            sscanf(argv[0],"%d",&swap->order[0]);
            sscanf(argv[1],"%d",&swap->order[1]);
            sscanf(argv[2],"%d",&swap->order[2]);
            sscanf(argv[3],"%d",&swap->order[3]);
        }
    }
    else
        swap->def_opts = 1;

    return (ST_SUCCESS);
}
int st_mcompand_getopts(eff_t effp, int n, char **argv) 
{
  char *subargv[6], *cp;
  int subargc, i, len;

  compand_t c = (compand_t) effp->priv;

  c->band_buf1 = c->band_buf2 = c->band_buf3 = 0;
  c->band_buf_len = 0;

  /* how many bands? */
  if (! (n&1)) {
    st_fail("mcompand accepts only an odd number of arguments:\n"
            "  mcompand quoted_compand_args [xover_freq quoted_compand_args [...]");
    return ST_EOF;
  }
  c->nBands = (n+1)>>1;

  if (! (c->bands = (struct comp_band *)malloc(c->nBands * sizeof(struct comp_band)))) {
    st_fail("Out of memory");
    return ST_EOF;
  }
  memset(c->bands,0,c->nBands * sizeof(struct comp_band));

  for (i=0;i<c->nBands;++i) {
    len = strlen(argv[i<<1]);
    if (parse_subarg(argv[i<<1],subargv,&subargc) != ST_SUCCESS)
      return ST_EOF;
    if (st_mcompand_getopts_1(&c->bands[i], subargc, &subargv[0]) != ST_SUCCESS)
      return ST_EOF;
    if (i == (c->nBands-1))
      c->bands[i].topfreq = 0;
    else {
      c->bands[i].topfreq = strtod(argv[(i<<1)+1],&cp);
      if (*cp) {
        st_fail("bad frequency in args to mcompand");
        return ST_EOF;
      }
      if ((i>0) && (c->bands[i].topfreq < c->bands[i-1].topfreq)) {
        st_fail("mcompand crossover frequencies must be in ascending order.");
        return ST_EOF;
      }
    }
  }

  return ST_SUCCESS;
}
/*
 * Process options
 */
int st_trim_getopts(eff_t effp, int n, char **argv) 
{
    trim_t trim = (trim_t) effp->priv;

    /* Do not know sample rate yet so hold off on completely parsing
     * time related strings.
     */
    switch (n) {
        case 2:
            trim->length_str = (char *)malloc(strlen(argv[1])+1);
            if (!trim->length_str)
            {
                st_fail("Could not allocate memory");
                return(ST_EOF);
            }
            strcpy(trim->length_str,argv[1]);
            /* Do a dummy parse to see if it will fail */
            if (st_parsesamples(0, trim->length_str,
                                &trim->length, 't') != ST_SUCCESS)
            {
                st_fail(TRIM_USAGE);
                return(ST_EOF);
            }
        case 1:
            trim->start_str = (char *)malloc(strlen(argv[0])+1);
            if (!trim->start_str)
            {
                st_fail("Could not allocate memory");
                return(ST_EOF);
            }
            strcpy(trim->start_str,argv[0]);
            /* Do a dummy parse to see if it will fail */
            if (st_parsesamples(0, trim->start_str,
                                &trim->start, 't') != ST_SUCCESS)
            {
                st_fail(TRIM_USAGE);
                return(ST_EOF);
            }
            break;
        default:
            st_fail(TRIM_USAGE);
            return ST_EOF;
            break;

    }
    return (ST_SUCCESS);
}
/*
 * Process options
 */
int st_earwax_getopts(eff_t effp, int n, char **argv) 
{
  /* no options */
  if (n){
    st_fail("The earwax filtering effect takes no options.\n");
    return (ST_EOF);
  }
  return (ST_SUCCESS);
}
int st_reverse_getopts(eff_t effp, int n, char **argv) 
{
        if (n)
        {
                st_fail("Reverse effect takes no options.");
                return (ST_EOF);
        }
        return(ST_SUCCESS);
}
예제 #14
0
/*
 * Prepare processing.
 * Do all initializations.
 */
int st_compand_start(eff_t effp)
{
    compand_t l = (compand_t) effp->priv;
    int i;

# ifdef DEBUG
    {
        fprintf(stderr, "Starting compand effect\n");
        fprintf(stderr, "\nRate %ld, size %d, encoding %d, output gain %g.\n",
                effp->outinfo.rate, effp->outinfo.size, effp->outinfo.encoding,
                l->outgain);
        fprintf(stderr, "%d input channel(s) expected: actually %d\n",
                l->expectedChannels, effp->outinfo.channels);
        fprintf(stderr, "\nAttack and decay rates\n"
                "======================\n");
        for (i = 0; i < l->expectedChannels; ++i)
            fprintf(stderr, "Channel %d: attack = %-12g decay = %-12g\n",
                    i, l->attackRate[i], l->decayRate[i]);
        fprintf(stderr, "\nTransfer function (linear values)\n"
                "=================  =============\n");
        for (i = 0; i < l->transferPoints; ++i)
            fprintf(stderr, "%12g -> %-12g\n",
                    l->transferIns[i], l->transferOuts[i]);
    }
# endif

    /* Convert attack and decay rates using number of samples */

    for (i = 0; i < l->expectedChannels; ++i) {
        if (l->attackRate[i] > 1.0/effp->outinfo.rate)
            l->attackRate[i] = 1.0 -
                               exp(-1.0/(effp->outinfo.rate * l->attackRate[i]));
        else
            l->attackRate[i] = 1.0;
        if (l->decayRate[i] > 1.0/effp->outinfo.rate)
            l->decayRate[i] = 1.0 -
                              exp(-1.0/(effp->outinfo.rate * l->decayRate[i]));
        else
            l->decayRate[i] = 1.0;
    }

    /* Allocate the delay buffer */
    l->delay_buf_size = l->delay * effp->outinfo.rate * effp->outinfo.channels;
    if (l->delay_buf_size > 0
            && (l->delay_buf = (st_sample_t *)malloc(sizeof(long) * l->delay_buf_size)) == NULL) {
        st_fail("Out of memory");
        return (ST_EOF);
    }
    for (i = 0;  i < l->delay_buf_size;  i++)
        l->delay_buf[i] = 0;
    l->delay_buf_ptr = 0;
    l->delay_buf_cnt = 0;
    l->delay_buf_full= 0;

    return (ST_SUCCESS);
}
/*
 * Process options
 */
int st_vibro_getopts(eff_t effp, int n, char **argv) 
{
	vibro_t vibro = (vibro_t) effp->priv;

	vibro->depth = 0.5;
	if ((n == 0) || !sscanf(argv[0], "%f", &vibro->speed) ||
		((n == 2) && !sscanf(argv[1], "%f", &vibro->depth)))
	{
		st_fail("Usage: vibro speed [ depth ]");
		return (ST_EOF);
	}
	if ((vibro->speed <= 0.001) || (vibro->speed > 30.0) || 
			(vibro->depth < 0.0) || (vibro->depth > 1.0))
	{
		st_fail("Vibro: speed must be < 30.0, 0.0 < depth < 1.0");
		return (ST_EOF);
	}
	return (ST_SUCCESS);
}
/*
 * Effect flow: a degenerate case: write input samples on temporary file,
 * don't generate any output samples.
 */
int st_reverse_flow(eff_t effp, st_sample_t *ibuf, st_sample_t *obuf, 
                    st_size_t *isamp, st_size_t *osamp)
{
        reverse_t reverse = (reverse_t) effp->priv;

        if (reverse->phase != WRITING)
        {
                st_fail("Internal error: reverse_flow called in wrong phase");
                return(ST_EOF);
        }
        if (fwrite((char *)ibuf, sizeof(st_sample_t), *isamp, reverse->fp)
            != *isamp)
        {
                st_fail("Reverse effect write error on temporary file\n");
                return(ST_EOF);
        }
        *osamp = 0;
        return(ST_SUCCESS);
}
/*
 * Processed signed long samples from ibuf to obuf.
 * Return number of samples processed.
 */
int st_mcompand_flow(eff_t effp, st_sample_t *ibuf, st_sample_t *obuf, 
                     st_size_t *isamp, st_size_t *osamp) {
  compand_t c = (compand_t) effp->priv;
  comp_band_t l;
  int len = ((*isamp > *osamp) ? *osamp : *isamp);
  int band, i;
  st_sample_t *abuf, *bbuf, *cbuf, *oldabuf;

  if (c->band_buf_len < len) {
    if ((! (c->band_buf1 = (st_sample_t *)realloc(c->band_buf1,len*sizeof(st_sample_t)))) ||
        (! (c->band_buf2 = (st_sample_t *)realloc(c->band_buf2,len*sizeof(st_sample_t)))) ||
        (! (c->band_buf3 = (st_sample_t *)realloc(c->band_buf3,len*sizeof(st_sample_t))))) {
      st_fail("Out of memory");
      return (ST_EOF);
    }
    c->band_buf_len = len;
  }

  /* split ibuf into bands using butterworths, pipe each band through st_mcompand_flow_1, then add back together and write to obuf */

  memset(obuf,0,len * sizeof *obuf);
  for (band=0,abuf=ibuf,bbuf=c->band_buf2,cbuf=c->band_buf1;band<c->nBands;++band) {
    l = &c->bands[band];

    if (l->topfreq)
      lowpass_flow(&l->filter, effp->outinfo.channels, abuf, bbuf, cbuf, len);
    else {
      bbuf = abuf;
      abuf = cbuf;
    }
    if (abuf == ibuf)
      abuf = c->band_buf3;
    (void)st_mcompand_flow_1(c,l,bbuf,abuf,len,effp->outinfo.channels);
    for (i=0;i<len;++i)
      obuf[i] += abuf[i];
    oldabuf = abuf;
    abuf = cbuf;
    cbuf = oldabuf;
  }

  for (i=0;i<len;++i) {
    if (obuf[i] < ST_SAMPLE_MIN) {
      obuf[i] = ST_SAMPLE_MIN;
    }
    else if (obuf[i] > ST_SAMPLE_MAX) {
      obuf[i] = ST_SAMPLE_MAX;
    }
  }

  *isamp = *osamp = len;

  return ST_SUCCESS;
}
int st_repeat_getopts(eff_t effp, int n, char **argv) 
{
        repeat_t repeat = (repeat_t)effp->priv;

        if (n != 1) {
                st_fail("Usage: repeat count]");
                return (ST_EOF);
        }

        if (!(sscanf(argv[0], "%i", &repeat->repeats))) {
                st_fail("repeat: could not parse repeat parameter");
                return (ST_EOF);
        }

        if (repeat->repeats < 0) {
                st_fail("repeat: repeat parameter must be positive");
                return (ST_EOF);
        }

        return (ST_SUCCESS);
}
int st_reverse_start(eff_t effp)
{
        reverse_t reverse = (reverse_t) effp->priv;
        reverse->fp = tmpfile();
        if (reverse->fp == NULL)
        {
                st_fail("Reverse effect can't create temporary file\n");
                return (ST_EOF);
        }
        reverse->phase = WRITING;
        return (ST_SUCCESS);
}
/*
 * Process options
 */
int st_mask_getopts(eff_t effp, int n, char **argv) 
{
	if (n)
	{
		st_fail("Mask effect takes no options.");
		return (ST_EOF);
	}
	/* should take # of bits */

	st_initrand();
	return (ST_SUCCESS);
}
/*
 * Process options
 */
int st_chorus_getopts(eff_t effp, int n, char **argv) 
{
        chorus_t chorus = (chorus_t) effp->priv;
        int i;

        chorus->num_chorus = 0;
        i = 0;

        if ( ( n < 7 ) || (( n - 2 ) % 5 ) )
        {
            st_fail("Usage: chorus gain-in gain-out delay decay speed depth [ -s | -t ]");
            return (ST_EOF);
        }

        sscanf(argv[i++], "%f", &chorus->in_gain);
        sscanf(argv[i++], "%f", &chorus->out_gain);
        while ( i < n ) {
                if ( chorus->num_chorus > MAX_CHORUS )
                {
                        st_fail("chorus: to many delays, use less than %i delays", MAX_CHORUS);
                        return (ST_EOF);
                }
                sscanf(argv[i++], "%f", &chorus->delay[chorus->num_chorus]);
                sscanf(argv[i++], "%f", &chorus->decay[chorus->num_chorus]);
                sscanf(argv[i++], "%f", &chorus->speed[chorus->num_chorus]);
                sscanf(argv[i++], "%f", &chorus->depth[chorus->num_chorus]);
                if ( !strcmp(argv[i], "-s"))
                        chorus->modulation[chorus->num_chorus] = MOD_SINE;
                else if ( ! strcmp(argv[i], "-t"))
                        chorus->modulation[chorus->num_chorus] = MOD_TRIANGLE;
                else
                {
                        st_fail("Usage: chorus gain-in gain-out delay decay speed [ -s | -t ]");
                        return (ST_EOF);
                }
                i++;
                chorus->num_chorus++;
        }
        return (ST_SUCCESS);
}
static int lowpass_setup (butterworth_crossover_t butterworth, double frequency, st_rate_t rate, int nchan) {
  double c;

  if (! (butterworth->xy_low = (struct xy *)malloc(nchan * sizeof(struct xy)))) {
    st_fail("Out of memory");
    return (ST_EOF);
  }
  memset(butterworth->xy_low,0,nchan * sizeof(struct xy));
  if (! (butterworth->xy_high = (struct xy *)malloc(nchan * sizeof(struct xy)))) {
    st_fail("Out of memory");
    return (ST_EOF);
  }
  memset(butterworth->xy_high,0,nchan * sizeof(struct xy));

  /* lowpass setup */
  butterworth->frequency_low = frequency/1.3;

  c = 1.0 / tan (M_PI * butterworth->frequency_low / rate);

  butterworth->a_low[0] = 1.0 / (1.0 + sqrt(2.0) * c + c * c);
  butterworth->a_low[1] = 2.0 * butterworth->a_low [0];
  butterworth->a_low[2] = butterworth->a_low [0];

  butterworth->b_low[0] = 2 * (1.0 - c * c) * butterworth->a_low[0];
  butterworth->b_low[1] = (1.0 - sqrt(2.0) * c + c * c) * butterworth->a_low[0];

  /* highpass setup */
  butterworth->frequency_high = frequency*1.3;

  c = tan (M_PI * butterworth->frequency_high / rate);

  butterworth->a_high[0] = 1.0 / (1.0 + sqrt (2.0) * c + c * c);
  butterworth->a_high[1] = -2.0 * butterworth->a_high[0];
  butterworth->a_high[2] = butterworth->a_high[0];

  butterworth->b_high[0] = 2 * (c * c - 1.0) * butterworth->a_high[0];
  butterworth->b_high[1] = (1.0 - sqrt(2.0) * c + c * c) * butterworth->a_high[0];

  return (ST_SUCCESS);
}
int st_reverse_drain(eff_t effp, st_sample_t *obuf, st_size_t *osamp)
{
        reverse_t reverse = (reverse_t) effp->priv;
        st_size_t len, nbytes;
        register int i, j;
        st_sample_t temp;

        if (reverse->phase == WRITING) {
                fflush(reverse->fp);
                fseek(reverse->fp, 0L, SEEK_END);
                reverse->pos = ftell(reverse->fp);
                if (reverse->pos % sizeof(st_sample_t) != 0)
                {
                        st_fail("Reverse effect finds odd temporary file\n");
                        return(ST_EOF);
                }
                reverse->phase = READING;
        }
        len = *osamp;
        nbytes = len * sizeof(st_sample_t);
        if (reverse->pos < nbytes) {
                nbytes = reverse->pos;
                len = nbytes / sizeof(st_sample_t);
        }
        reverse->pos -= nbytes;
        fseek(reverse->fp, reverse->pos, SEEK_SET);
        if (fread((char *)obuf, sizeof(st_sample_t), len, reverse->fp) != len)
        {
                st_fail("Reverse effect read error from temporary file\n");
                return(ST_EOF);
        }
        for (i = 0, j = len-1; i < j; i++, j--) {
                temp = obuf[i];
                obuf[i] = obuf[j];
                obuf[j] = temp;
        }
        *osamp = len;
        return(ST_SUCCESS);
}
int st_repeat_start(eff_t effp)
{
        repeat_t repeat = (repeat_t)effp->priv;

        if ((repeat->fp = tmpfile()) == NULL) {
                st_fail("repeat: could not create temporary file");
                return (ST_EOF);
        }

        repeat->first_drain = 1;
        
        return (ST_SUCCESS);
}
/*
 * Process options
 */
int st_band_getopts(eff_t effp, int n, char **argv) 
{
	band_t band = (band_t) effp->priv;

	band->noise = 0;
	if (n > 0 && !strcmp(argv[0], "-n")) {
		band->noise = 1;
		n--;
		argv++;
	}
	if ((n < 1) || !sscanf(argv[0], "%f", &band->center))
	{
		st_fail("Usage: band [ -n ] center [ width ]");
		return (ST_EOF);
	}
	band->width = band->center / 2;
	if ((n >= 2) && !sscanf(argv[1], "%f", &band->width))
	{
		st_fail("Usage: band [ -n ] center [ width ]");
		return (ST_EOF);
	}
	return (ST_SUCCESS);
}
int st_repeat_flow(eff_t effp, st_sample_t *ibuf, st_sample_t *obuf,
                st_size_t *isamp, st_size_t *osamp)
{
        repeat_t repeat = (repeat_t)effp->priv;

        if (fwrite((char *)ibuf, sizeof(st_sample_t), *isamp, repeat->fp) !=
                        *isamp) {
                st_fail("repeat: write error on temporary file\n");
                return (ST_EOF);
        }

        *osamp = 0;

        return (ST_SUCCESS);
}
/*
 * Prepare processing.
 * Do all initializations.
 */
int st_mcompand_start(eff_t effp)
{
  compand_t c = (compand_t) effp->priv;
  comp_band_t l;
  int band, i;
  
  for (band=0;band<c->nBands;++band) {
    l = &c->bands[band];
    l->delay_size = c->bands[band].delay * effp->outinfo.rate * effp->outinfo.channels;
    if (l->delay_size > c->delay_buf_size)
      c->delay_buf_size = l->delay_size;
  }

  for (band=0;band<c->nBands;++band) {
    l = &c->bands[band];
    /* Convert attack and decay rates using number of samples */

    for (i = 0; i < l->expectedChannels; ++i) {
      if (l->attackRate[i] > 1.0/effp->outinfo.rate)
        l->attackRate[i] = 1.0 -
          exp(-1.0/(effp->outinfo.rate * l->attackRate[i]));
      else
        l->attackRate[i] = 1.0;
      if (l->decayRate[i] > 1.0/effp->outinfo.rate)
        l->decayRate[i] = 1.0 -
          exp(-1.0/(effp->outinfo.rate * l->decayRate[i]));
      else
        l->decayRate[i] = 1.0;
    }

    /* Allocate the delay buffer */
    if (c->delay_buf_size > 0) {
      if ((l->delay_buf = (st_sample_t *)malloc(sizeof(long) * c->delay_buf_size)) == NULL) {
        st_fail("Out of memory");
        return (ST_EOF);
      }
      for (i = 0;  i < c->delay_buf_size;  i++)
        l->delay_buf[i] = 0;

    }
    l->delay_buf_ptr = 0;
    l->delay_buf_cnt = 0;

    if (l->topfreq != 0)
      lowpass_setup(&l->filter, l->topfreq, effp->outinfo.rate, effp->outinfo.channels);
  }
  return (ST_SUCCESS);
}
/*
 * Prepare processing.
 */
int st_vibro_start(eff_t effp)
{
	vibro_t vibro = (vibro_t) effp->priv;

	vibro->length = effp->ininfo.rate / vibro->speed;
	if (! (vibro->sinetab = (short*) malloc(vibro->length * sizeof(short))))
	{
		st_fail("Vibro: Cannot malloc %d bytes",
			vibro->length * sizeof(short));
		return (ST_EOF);
	}

	sine(vibro->sinetab, vibro->length, vibro->depth);
	vibro->counter = 0;
	return (ST_SUCCESS);
}
/*
 * Prepare processing.
 */
int st_band_start(eff_t effp)
{
	band_t band = (band_t) effp->priv;
	if (band->center > effp->ininfo.rate/2)
	{
		st_fail("Band: center must be < minimum data rate/2\n");
		return (ST_EOF);
	}

	band->C = exp(-2*M_PI*band->width/effp->ininfo.rate);
	band->B = -4*band->C/(1+band->C)*
		cos(2*M_PI*band->center/effp->ininfo.rate);
	if (band->noise)
		band->A = sqrt(((1+band->C)*(1+band->C)-band->B *
			band->B)*(1-band->C)/(1+band->C));
	else
		band->A = sqrt(1-band->B*band->B/(4*band->C))*(1-band->C);
	band->out1 = band->out2 = 0.0;
	return (ST_SUCCESS);
}
/*
 * Start processing
 */
int st_vol_start(eff_t effp)
{
    vol_t vol = (vol_t) effp->priv;
    
    if (effp->outinfo.channels != effp->ininfo.channels)
    {
        st_warn("VOL cannot handle different channels (in=%d, out=%d)"
             " use avg or pan", effp->ininfo.channels, effp->outinfo.channels);
    }

    if (effp->outinfo.rate != effp->ininfo.rate)
    {
        st_fail("VOL cannot handle different rates (in=%ld, out=%ld)"
             " use resample or rate", effp->ininfo.rate, effp->outinfo.rate);
        return ST_EOF;
    }

    vol->clipped = 0;
    vol->limited = 0;
    vol->totalprocessed = 0;

    return ST_SUCCESS;
}