Ejemplo n.º 1
0
static void
gst_audio_fx_base_fir_filter_dispose (GObject * object)
{
  GstAudioFXBaseFIRFilter *self = GST_AUDIO_FX_BASE_FIR_FILTER (object);

  g_free (self->buffer);
  self->buffer = NULL;
  self->buffer_length = 0;

  g_free (self->kernel);
  self->kernel = NULL;

  gst_fft_f64_free (self->fft);
  self->fft = NULL;
  gst_fft_f64_free (self->ifft);
  self->ifft = NULL;

  g_free (self->frequency_response);
  self->frequency_response = NULL;

  g_free (self->fft_buffer);
  self->fft_buffer = NULL;

  G_OBJECT_CLASS (parent_class)->dispose (object);
}
static void
gst_audio_fx_base_fir_filter_finalize (GObject * object)
{
  GstAudioFXBaseFIRFilter *self = GST_AUDIO_FX_BASE_FIR_FILTER (object);

  g_free (self->buffer);
  g_free (self->kernel);
  gst_fft_f64_free (self->fft);
  gst_fft_f64_free (self->ifft);
  g_free (self->frequency_response);
  g_free (self->fft_buffer);
  g_mutex_clear (&self->lock);

  G_OBJECT_CLASS (parent_class)->finalize (object);
}
static void
on_rate_changed (GstElement * element, gint rate, gpointer user_data)
{
  GValueArray *va;
  GValue v = { 0, };
  GstFFTF64 *fft;
  GstFFTF64Complex frequency_response[17];
  gdouble tmp[32];
  gdouble filter_kernel[32];
  guint i;

  /* Create the frequency response: zero outside
   * a small frequency band */
  for (i = 0; i < 17; i++) {
    if (i < 5 || i > 11)
      frequency_response[i].r = 0.0;
    else
      frequency_response[i].r = 1.0;

    frequency_response[i].i = 0.0;
  }

  /* Calculate the inverse FT of the frequency response */
  fft = gst_fft_f64_new (32, TRUE);
  gst_fft_f64_inverse_fft (fft, frequency_response, tmp);
  gst_fft_f64_free (fft);

  /* Shift the inverse FT of the frequency response by 16,
   * i.e. the half of the kernel length to get the
   * impulse response. See http://www.dspguide.com/ch17/1.htm
   * for more information.
   */
  for (i = 0; i < 32; i++)
    filter_kernel[i] = tmp[(i + 16) % 32];

  /* Apply the hamming window to the impulse response to get
   * a better result than given from the rectangular window
   */
  for (i = 0; i < 32; i++)
    filter_kernel[i] *= (0.54 - 0.46 * cos (2 * G_PI * i / 32));

  va = g_value_array_new (1);

  g_value_init (&v, G_TYPE_DOUBLE);
  for (i = 0; i < 32; i++) {
    g_value_set_double (&v, filter_kernel[i]);
    g_value_array_append (va, &v);
    g_value_reset (&v);
  }
  g_object_set (G_OBJECT (element), "kernel", va, NULL);
  /* Latency is 1/2 of the kernel length for this method of
   * calculating a filter kernel from the frequency response
   */
  g_object_set (G_OBJECT (element), "latency", (gint64) (32 / 2), NULL);
  g_value_array_free (va);
}
/* Element class */
static void
    gst_audio_fx_base_fir_filter_calculate_frequency_response
    (GstAudioFXBaseFIRFilter * self)
{
  gst_fft_f64_free (self->fft);
  self->fft = NULL;
  gst_fft_f64_free (self->ifft);
  self->ifft = NULL;
  g_free (self->frequency_response);
  self->frequency_response_length = 0;
  g_free (self->fft_buffer);
  self->fft_buffer = NULL;

  if (self->kernel && self->kernel_length >= FFT_THRESHOLD
      && !self->low_latency) {
    guint block_length, i;
    gdouble *kernel_tmp, *kernel = self->kernel;

    /* We process 4 * kernel_length samples per pass in FFT mode */
    block_length = 4 * self->kernel_length;
    block_length = gst_fft_next_fast_length (block_length);
    self->block_length = block_length;

    kernel_tmp = g_new0 (gdouble, block_length);
    memcpy (kernel_tmp, kernel, self->kernel_length * sizeof (gdouble));

    self->fft = gst_fft_f64_new (block_length, FALSE);
    self->ifft = gst_fft_f64_new (block_length, TRUE);
    self->frequency_response_length = block_length / 2 + 1;
    self->frequency_response =
        g_new (GstFFTF64Complex, self->frequency_response_length);
    gst_fft_f64_fft (self->fft, kernel_tmp, self->frequency_response);
    g_free (kernel_tmp);

    /* Normalize to make sure IFFT(FFT(x)) == x */
    for (i = 0; i < self->frequency_response_length; i++) {
      self->frequency_response[i].r /= block_length;
      self->frequency_response[i].i /= block_length;
    }
  }
}