# gst-plugins-good Elements

    /* GStreamer
     * Copyright (C) 2009 Sebastian Droege <sebastian.droege@collabora.co.uk>
     *
     * This library is free software; you can redistribute it and/or
     * modify it under the terms of the GNU Library General Public
     * License as published by the Free Software Foundation; either
     * version 2 of the License, or (at your option) any later version.
     *
     * This library is distributed in the hope that it will be useful,
     * but WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     * Library General Public License for more details.
     *
     * You should have received a copy of the GNU Library General Public
     * License along with this library; if not, write to the
     * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
     * Boston, MA 02110-1301, USA.
     */

    /* This small sample application creates a bandpass FIR filter
     * by transforming the frequency response to the filter kernel.
     */

    /* FIXME 0.11: suppress warnings for deprecated API such as GValueArray
     * with newer GLib versions (>= 2.31.0) */
    #define GLIB_DISABLE_DEPRECATION_WARNINGS

    #include <string.h>
    #include <math.h>

    #include <gst/gst.h>
    #include <gst/fft/gstfftf64.h>

    static gboolean
    on_message (GstBus * bus, GstMessage * message, gpointer user_data)
    {
      GMainLoop *loop = (GMainLoop *) user_data;

      switch (GST_MESSAGE_TYPE (message)) {
        case GST_MESSAGE_ERROR:
          g_error ("Got ERROR");
          g_main_loop_quit (loop);
          break;
        case GST_MESSAGE_WARNING:
          g_warning ("Got WARNING");
          g_main_loop_quit (loop);
          break;
        case GST_MESSAGE_EOS:
          g_main_loop_quit (loop);
          break;
        default:
          break;
      }

      return TRUE;
    }

    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);
    }

    gint
    main (gint argc, gchar * argv[])
    {
      GstElement *pipeline, *src, *filter, *conv, *sink;
      GstBus *bus;
      GMainLoop *loop;

      gst_init (NULL, NULL);

      pipeline = gst_element_factory_make ("pipeline", NULL);

      src = gst_element_factory_make ("audiotestsrc", NULL);
      g_object_set (G_OBJECT (src), "wave", 5, NULL);

      filter = gst_element_factory_make ("audiofirfilter", NULL);
      g_signal_connect (G_OBJECT (filter), "rate-changed",
          G_CALLBACK (on_rate_changed), NULL);

      conv = gst_element_factory_make ("audioconvert", NULL);

      sink = gst_element_factory_make ("autoaudiosink", NULL);
      g_return_val_if_fail (sink != NULL, -1);

      gst_bin_add_many (GST_BIN (pipeline), src, filter, conv, sink, NULL);
      if (!gst_element_link_many (src, filter, conv, sink, NULL)) {
        g_error ("Failed to link elements");
        return -2;
      }

      loop = g_main_loop_new (NULL, FALSE);

      bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
      gst_bus_add_signal_watch (bus);
      g_signal_connect (G_OBJECT (bus), "message", G_CALLBACK (on_message), loop);
      gst_object_unref (GST_OBJECT (bus));

      if (gst_element_set_state (pipeline,
              GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) {
        g_error ("Failed to go into PLAYING state");
        return -3;
      }

      g_main_loop_run (loop);

      gst_element_set_state (pipeline, GST_STATE_NULL);

      g_main_loop_unref (loop);
      gst_object_unref (pipeline);

      return 0;
    }

    /* GStreamer
     * Copyright (C) 2009 Sebastian Droege <sebastian.droege@collabora.co.uk>
     *
     * This library is free software; you can redistribute it and/or
     * modify it under the terms of the GNU Library General Public
     * License as published by the Free Software Foundation; either
     * version 2 of the License, or (at your option) any later version.
     *
     * This library is distributed in the hope that it will be useful,
     * but WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     * Library General Public License for more details.
     *
     * You should have received a copy of the GNU Library General Public
     * License along with this library; if not, write to the
     * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
     * Boston, MA 02110-1301, USA.
     */

    /* This small sample application creates a lowpass IIR filter
     * and applies it to white noise.
     * See http://www.dspguide.com/ch19/2.htm for a description
     * of the IIR filter that is used.
     */

    /* FIXME 0.11: suppress warnings for deprecated API such as GValueArray
     * with newer GLib versions (>= 2.31.0) */
    #define GLIB_DISABLE_DEPRECATION_WARNINGS

    #include <string.h>
    #include <math.h>

    #include <gst/gst.h>

    /* Cutoff of 4000 Hz */
    #define CUTOFF (4000.0)

    static gboolean
    on_message (GstBus * bus, GstMessage * message, gpointer user_data)
    {
      GMainLoop *loop = (GMainLoop *) user_data;

      switch (GST_MESSAGE_TYPE (message)) {
        case GST_MESSAGE_ERROR:
          g_error ("Got ERROR");
          g_main_loop_quit (loop);
          break;
        case GST_MESSAGE_WARNING:
          g_warning ("Got WARNING");
          g_main_loop_quit (loop);
          break;
        case GST_MESSAGE_EOS:
          g_main_loop_quit (loop);
          break;
        default:
          break;
      }

      return TRUE;
    }

    static void
    on_rate_changed (GstElement * element, gint rate, gpointer user_data)
    {
      GValueArray *va;
      GValue v = { 0, };
      gdouble x;

      if (rate / 2.0 > CUTOFF)
        x = exp (-2.0 * G_PI * (CUTOFF / rate));
      else
        x = 0.0;

      va = g_value_array_new (1);

      g_value_init (&v, G_TYPE_DOUBLE);
      g_value_set_double (&v, 1.0 - x);
      g_value_array_append (va, &v);
      g_value_reset (&v);
      g_object_set (G_OBJECT (element), "a", va, NULL);
      g_value_array_free (va);

      va = g_value_array_new (1);
      g_value_set_double (&v, x);
      g_value_array_append (va, &v);
      g_value_reset (&v);
      g_object_set (G_OBJECT (element), "b", va, NULL);
      g_value_array_free (va);
    }

    gint
    main (gint argc, gchar * argv[])
    {
      GstElement *pipeline, *src, *filter, *conv, *sink;
      GstBus *bus;
      GMainLoop *loop;

      gst_init (NULL, NULL);

      pipeline = gst_element_factory_make ("pipeline", NULL);

      src = gst_element_factory_make ("audiotestsrc", NULL);
      g_object_set (G_OBJECT (src), "wave", 5, NULL);

      filter = gst_element_factory_make ("audioiirfilter", NULL);
      g_signal_connect (G_OBJECT (filter), "rate-changed",
          G_CALLBACK (on_rate_changed), NULL);

      conv = gst_element_factory_make ("audioconvert", NULL);

      sink = gst_element_factory_make ("autoaudiosink", NULL);
      g_return_val_if_fail (sink != NULL, -1);

      gst_bin_add_many (GST_BIN (pipeline), src, filter, conv, sink, NULL);
      if (!gst_element_link_many (src, filter, conv, sink, NULL)) {
        g_error ("Failed to link elements");
        return -2;
      }

      loop = g_main_loop_new (NULL, FALSE);

      bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
      gst_bus_add_signal_watch (bus);
      g_signal_connect (G_OBJECT (bus), "message", G_CALLBACK (on_message), loop);
      gst_object_unref (GST_OBJECT (bus));

      if (gst_element_set_state (pipeline,
              GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) {
        g_error ("Failed to go into PLAYING state");
        return -3;
      }

      g_main_loop_run (loop);

      gst_element_set_state (pipeline, GST_STATE_NULL);

      g_main_loop_unref (loop);
      gst_object_unref (pipeline);

      return 0;
    }

    /* GStreamer
     * Copyright (C) 2000,2001,2002,2003,2005
     *           Thomas Vander Stichele <thomas at apestaart dot org>
     *
     * This library is free software; you can redistribute it and/or
     * modify it under the terms of the GNU Library General Public
     * License as published by the Free Software Foundation; either
     * version 2 of the License, or (at your option) any later version.
     *
     * This library is distributed in the hope that it will be useful,
     * but WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     * Library General Public License for more details.
     *
     * You should have received a copy of the GNU Library General Public
     * License along with this library; if not, write to the
     * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
     * Boston, MA 02110-1301, USA.
     */

    #include <string.h>
    #include <math.h>

    #define GLIB_DISABLE_DEPRECATION_WARNINGS

    #include <gst/gst.h>

    static gboolean
    message_handler (GstBus * bus, GstMessage * message, gpointer data)
    {

      if (message->type == GST_MESSAGE_ELEMENT) {
        const GstStructure *s = gst_message_get_structure (message);
        const gchar *name = gst_structure_get_name (s);

        if (strcmp (name, "level") == 0) {
          gint channels;
          GstClockTime endtime;
          gdouble rms_dB, peak_dB, decay_dB;
          gdouble rms;
          const GValue *array_val;
          const GValue *value;
          GValueArray *rms_arr, *peak_arr, *decay_arr;
          gint i;

          if (!gst_structure_get_clock_time (s, "endtime", &endtime))
            g_warning ("Could not parse endtime");

          /* the values are packed into GValueArrays with the value per channel */
          array_val = gst_structure_get_value (s, "rms");
          rms_arr = (GValueArray *) g_value_get_boxed (array_val);

          array_val = gst_structure_get_value (s, "peak");
          peak_arr = (GValueArray *) g_value_get_boxed (array_val);

          array_val = gst_structure_get_value (s, "decay");
          decay_arr = (GValueArray *) g_value_get_boxed (array_val);

          /* we can get the number of channels as the length of any of the value
           * arrays */
          channels = rms_arr->n_values;
          g_print ("endtime: %" GST_TIME_FORMAT ", channels: %d\n",
              GST_TIME_ARGS (endtime), channels);
          for (i = 0; i < channels; ++i) {

            g_print ("channel %d\n", i);
            value = g_value_array_get_nth (rms_arr, i);
            rms_dB = g_value_get_double (value);

            value = g_value_array_get_nth (peak_arr, i);
            peak_dB = g_value_get_double (value);

            value = g_value_array_get_nth (decay_arr, i);
            decay_dB = g_value_get_double (value);
            g_print ("    RMS: %f dB, peak: %f dB, decay: %f dB\n",
                rms_dB, peak_dB, decay_dB);

            /* converting from dB to normal gives us a value between 0.0 and 1.0 */
            rms = pow (10, rms_dB / 20);
            g_print ("    normalized rms value: %f\n", rms);
          }
        }
      }
      /* we handled the message we want, and ignored the ones we didn't want.
       * so the core can unref the message for us */
      return TRUE;
    }

    int
    main (int argc, char *argv[])
    {
      GstElement *audiotestsrc, *audioconvert, *level, *fakesink;
      GstElement *pipeline;
      GstCaps *caps;
      GstBus *bus;
      guint watch_id;
      GMainLoop *loop;

      gst_init (&argc, &argv);

      caps = gst_caps_from_string ("audio/x-raw,channels=2");

      pipeline = gst_pipeline_new (NULL);
      g_assert (pipeline);
      audiotestsrc = gst_element_factory_make ("audiotestsrc", NULL);
      g_assert (audiotestsrc);
      audioconvert = gst_element_factory_make ("audioconvert", NULL);
      g_assert (audioconvert);
      level = gst_element_factory_make ("level", NULL);
      g_assert (level);
      fakesink = gst_element_factory_make ("fakesink", NULL);
      g_assert (fakesink);

      gst_bin_add_many (GST_BIN (pipeline), audiotestsrc, audioconvert, level,
          fakesink, NULL);
      if (!gst_element_link (audiotestsrc, audioconvert))
        g_error ("Failed to link audiotestsrc and audioconvert");
      if (!gst_element_link_filtered (audioconvert, level, caps))
        g_error ("Failed to link audioconvert and level");
      if (!gst_element_link (level, fakesink))
        g_error ("Failed to link level and fakesink");

      /* make sure we'll get messages */
      g_object_set (G_OBJECT (level), "post-messages", TRUE, NULL);
      /* run synced and not as fast as we can */
      g_object_set (G_OBJECT (fakesink), "sync", TRUE, NULL);

      bus = gst_element_get_bus (pipeline);
      watch_id = gst_bus_add_watch (bus, message_handler, NULL);

      gst_element_set_state (pipeline, GST_STATE_PLAYING);

      /* we need to run a GLib main loop to get the messages */
      loop = g_main_loop_new (NULL, FALSE);
      g_main_loop_run (loop);

      g_source_remove (watch_id);
      g_main_loop_unref (loop);
      return 0;
    }

    /* GStreamer
     * Copyright (C) 2006 Stefan Kost <ensonic@users.sf.net>
     * Copyright (C) 2008 Jan Schmidt <jan.schmidt@sun.com>
     *
     * This library is free software; you can redistribute it and/or
     * modify it under the terms of the GNU Library General Public
     * License as published by the Free Software Foundation; either
     * version 2 of the License, or (at your option) any later version.
     *
     * This library is distributed in the hope that it will be useful,
     * but WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     * Library General Public License for more details.
     *
     * You should have received a copy of the GNU Library General Public
     * License along with this library; if not, write to the
     * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
     * Boston, MA 02110-1301, USA.
     */

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <gst/gst.h>

    static guint spect_bands = 20;

    #define AUDIOFREQ 32000

    /* receive spectral data from element message */
    static gboolean
    message_handler (GstBus * bus, GstMessage * message, gpointer data)
    {
      if (message->type == GST_MESSAGE_ELEMENT) {
        const GstStructure *s = gst_message_get_structure (message);
        const gchar *name = gst_structure_get_name (s);
        GstClockTime endtime;

        if (strcmp (name, "spectrum") == 0) {
          const GValue *magnitudes;
          const GValue *phases;
          const GValue *mag, *phase;
          gdouble freq;
          guint i;

          if (!gst_structure_get_clock_time (s, "endtime", &endtime))
            endtime = GST_CLOCK_TIME_NONE;

          g_print ("New spectrum message, endtime %" GST_TIME_FORMAT "\n",
              GST_TIME_ARGS (endtime));

          magnitudes = gst_structure_get_value (s, "magnitude");
          phases = gst_structure_get_value (s, "phase");

          for (i = 0; i < spect_bands; ++i) {
            freq = (gdouble) ((AUDIOFREQ / 2) * i + AUDIOFREQ / 4) / spect_bands;
            mag = gst_value_list_get_value (magnitudes, i);
            phase = gst_value_list_get_value (phases, i);

            if (mag != NULL && phase != NULL) {
              g_print ("band %d (freq %g): magnitude %f dB phase %f\n", i, freq,
                  g_value_get_float (mag), g_value_get_float (phase));
            }
          }
          g_print ("\n");
        }
      }
      return TRUE;
    }

    int
    main (int argc, char *argv[])
    {
      GstElement *bin;
      GstElement *src, *audioconvert, *spectrum, *sink;
      GstBus *bus;
      GstCaps *caps;
      GMainLoop *loop;

      gst_init (&argc, &argv);

      bin = gst_pipeline_new ("bin");

      src = gst_element_factory_make ("audiotestsrc", "src");
      g_object_set (G_OBJECT (src), "wave", 0, "freq", 6000.0, NULL);
      audioconvert = gst_element_factory_make ("audioconvert", NULL);
      g_assert (audioconvert);

      spectrum = gst_element_factory_make ("spectrum", "spectrum");
      g_object_set (G_OBJECT (spectrum), "bands", spect_bands, "threshold", -80,
          "post-messages", TRUE, "message-phase", TRUE, NULL);

      sink = gst_element_factory_make ("fakesink", "sink");
      g_object_set (G_OBJECT (sink), "sync", TRUE, NULL);

      gst_bin_add_many (GST_BIN (bin), src, audioconvert, spectrum, sink, NULL);

      caps = gst_caps_new_simple ("audio/x-raw",
          "rate", G_TYPE_INT, AUDIOFREQ, NULL);

      if (!gst_element_link (src, audioconvert) ||
          !gst_element_link_filtered (audioconvert, spectrum, caps) ||
          !gst_element_link (spectrum, sink)) {
        fprintf (stderr, "can't link elements\n");
        exit (1);
      }
      gst_caps_unref (caps);

      bus = gst_element_get_bus (bin);
      gst_bus_add_watch (bus, message_handler, NULL);
      gst_object_unref (bus);

      gst_element_set_state (bin, GST_STATE_PLAYING);

      /* we need to run a GLib main loop to get the messages */
      loop = g_main_loop_new (NULL, FALSE);
      g_main_loop_run (loop);

      gst_element_set_state (bin, GST_STATE_NULL);

      gst_object_unref (bin);

      return 0;
    }