#! /usr/local/bin/pvtool

#define USAGE_MESSAGE "\
\tfreqform <input pv file> <output pv file> <freq ratio>[<threshold>]\n\
\n\
This program attempts to pitchshift an fft file, leaving formants intact.\n\
See makeenv for details of threshold parameter. Defaults to 0.1.\n"

#define DEFAULT_THRESHOLD 0.1

int
pvaction (void)
{
  int i, j, bin1, bin2;
  float freq_shift, bin_to_read, dbins, frac;
  float threshold = DEFAULT_THRESHOLD;

  if (parameter_count < 1)
    exit (pvtool_error ("Too few parameters"));

  freq_shift = fparameter[0];
  printf ("Shifting by frequency ratio %f.\n", freq_shift);

  if (parameter_count >= 2)
    {
      threshold = fparameter[1];
      printf ("Using threshold value %f.\n", threshold);
    }

  dbins = (float) bins;

  for (i = 0; i < OUTPUT_FRAMES; i++)
    for (j = 0; j < bins; j++)
      {
	bin_to_read = ((float) j) / freq_shift;
	bin1 = (int) bin_to_read;
	bin2 = bin1 + 1;
	frac = bin_to_read - (float) bin1;

	if (bin2 >= bins)
	  {
	    OUTPUT_PHIDOT (i, j) = bin_to_freq (j);
	    OUTPUT_MAG (i, j) = 0;
	  }
	else
	  {
	    OUTPUT_MAG (i, j) =
	      ((((1 - frac)
		 * spectral_envelope_independent_component
		 (1, i, bin1, threshold))
		+ (frac
		   * spectral_envelope_independent_component
		   (1, i, bin2, threshold)))
	       * (spectral_envelope_component
		  (1, i, j, threshold)));
	    
	    /* I'm not at all sure about this, but it doesn't sound
	       too bad. Weighting is just on freq position. Also see
	       freqshft. */
	    OUTPUT_PHIDOT (i, j) = freq_shift *
	      ((1 - frac) * INPUT1_PHIDOT (i, bin1)
	       + frac * INPUT1_PHIDOT (i, bin2));
	  }
      }
  return (0);
}
