void lsx_set_dft_filter(dft_filter_t *f, double *h, int n, int post_peak)
{
  int i;
  f->num_taps = n;
  f->post_peak = post_peak;
  f->dft_length = lsx_set_dft_length(f->num_taps);
  f->coefs = lsx_calloc(f->dft_length, sizeof(*f->coefs));
  for (i = 0; i < f->num_taps; ++i)
    f->coefs[(i + f->dft_length - f->num_taps + 1) & (f->dft_length - 1)] = h[i] / f->dft_length * 2;
  lsx_safe_rdft(f->dft_length, 1, f->coefs);
  free(h);
}
static void init_dft_filter(rate_shared_t * p, unsigned which, int num_taps,
    sox_sample_t const h[], double Fp, double Fc, double Fn, double att,
    int multiplier, double phase, sox_bool allow_aliasing)
{
  dft_filter_t * f = &p->half_band[which];
  int dft_length, i;

  if (f->num_taps)
    return;
  if (h) { // for half_fir_coefs_low
    dft_length = lsx_set_dft_length(num_taps);
    f->coefs = lsx_aligned_calloc(dft_length, sizeof(*f->coefs));
    for (i = 0; i < num_taps; ++i)
      f->coefs[(i + dft_length - num_taps + 1) & (dft_length - 1)]
          = h[abs(num_taps / 2 - i)] / dft_length * 2 * multiplier;
    f->post_peak = num_taps / 2;
  }
  else {
    double * h2 = lsx_design_lpf(Fp, Fc, Fn, allow_aliasing, att, &num_taps, 0, -1.);

    if (phase != 50)
      lsx_fir_to_phase(&h2, &num_taps, &f->post_peak, phase);
    else f->post_peak = num_taps / 2;

    dft_length = lsx_set_dft_length(num_taps);
    f->coefs = lsx_aligned_calloc(dft_length, sizeof(*f->coefs));
    for (i = 0; i < num_taps; ++i)
      f->coefs[(i + dft_length - num_taps + 1) & (dft_length - 1)]
          = h2[i] / dft_length * 2 * multiplier;
    lsx_free(h2);
  }
  assert(num_taps & 1);
  f->num_taps = num_taps;
  f->dft_length = dft_length;
  f->tmp_buf = lsx_aligned_malloc(dft_length*sizeof(FFTComplex)/2);
  ff_rdft_x(dft_length, 1, f->coefs, f->tmp_buf);
}