Add audioiirfilter and audiofirfilter elements which allow generic IIR/FIR filters...
authorSebastian Dröge <slomo@circular-chaos.org>
Tue, 13 Jan 2009 19:23:57 +0000 (19:23 +0000)
committerSebastian Dröge <slomo@circular-chaos.org>
Tue, 13 Jan 2009 19:23:57 +0000 (19:23 +0000)
Original commit message from CVS:
* configure.ac:
* gst/audiofx/Makefile.am:
* gst/audiofx/audiofirfilter.c: (gst_audio_fir_filter_base_init),
(gst_audio_fir_filter_class_init),
(gst_audio_fir_filter_update_kernel), (gst_audio_fir_filter_init),
(gst_audio_fir_filter_setup), (gst_audio_fir_filter_finalize),
(gst_audio_fir_filter_set_property),
(gst_audio_fir_filter_get_property):
* gst/audiofx/audiofirfilter.h:
* gst/audiofx/audiofx.c: (plugin_init):
* gst/audiofx/audioiirfilter.c: (gst_audio_iir_filter_base_init),
(gst_audio_iir_filter_class_init),
(gst_audio_iir_filter_update_coefficients),
(gst_audio_iir_filter_init), (gst_audio_iir_filter_setup),
(gst_audio_iir_filter_finalize),
(gst_audio_iir_filter_set_property),
(gst_audio_iir_filter_get_property):
* gst/audiofx/audioiirfilter.h:
Add audioiirfilter and audiofirfilter elements which allow
generic IIR/FIR filters to be implemented by providing the
filter coefficients. Fixes bug #567577.
* docs/plugins/Makefile.am:
* docs/plugins/gst-plugins-good-plugins-docs.sgml:
* docs/plugins/gst-plugins-good-plugins-sections.txt:
* docs/plugins/gst-plugins-good-plugins.args:
* docs/plugins/gst-plugins-good-plugins.hierarchy:
* docs/plugins/gst-plugins-good-plugins.signals:
* docs/plugins/inspect/plugin-alaw.xml:
* docs/plugins/inspect/plugin-audiofx.xml:
* docs/plugins/inspect/plugin-avi.xml:
* docs/plugins/inspect/plugin-flac.xml:
* docs/plugins/inspect/plugin-mulaw.xml:
* docs/plugins/inspect/plugin-video4linux2.xml:
* docs/plugins/inspect/plugin-wavparse.xml:
Add documentation for the audioiirfilter and audiofirfilter
elements.
* tests/check/Makefile.am:
* tests/check/elements/audiofirfilter.c: (on_message),
(on_rate_changed), (on_handoff), (GST_START_TEST),
(audiofirfilter_suite):
* tests/check/elements/audioiirfilter.c: (on_message),
(on_rate_changed), (on_handoff), (GST_START_TEST),
(audioiirfilter_suite):
* tests/examples/Makefile.am:
* tests/examples/audiofx/Makefile.am:
* tests/examples/audiofx/firfilter-example.c: (on_message),
(on_rate_changed), (main):
* tests/examples/audiofx/iirfilter-example.c: (on_message),
(on_rate_changed), (main):
Add unit tests and example applications for the two filter
elements.

28 files changed:
ChangeLog
configure.ac
docs/plugins/Makefile.am
docs/plugins/gst-plugins-good-plugins-docs.sgml
docs/plugins/gst-plugins-good-plugins-sections.txt
docs/plugins/gst-plugins-good-plugins.args
docs/plugins/gst-plugins-good-plugins.hierarchy
docs/plugins/gst-plugins-good-plugins.signals
docs/plugins/inspect/plugin-alaw.xml
docs/plugins/inspect/plugin-audiofx.xml
docs/plugins/inspect/plugin-avi.xml
docs/plugins/inspect/plugin-flac.xml
docs/plugins/inspect/plugin-mulaw.xml
docs/plugins/inspect/plugin-video4linux2.xml
docs/plugins/inspect/plugin-wavparse.xml
gst/audiofx/Makefile.am
gst/audiofx/audiofirfilter.c [new file with mode: 0644]
gst/audiofx/audiofirfilter.h [new file with mode: 0644]
gst/audiofx/audiofx.c
gst/audiofx/audioiirfilter.c [new file with mode: 0644]
gst/audiofx/audioiirfilter.h [new file with mode: 0644]
tests/check/Makefile.am
tests/check/elements/audiofirfilter.c [new file with mode: 0644]
tests/check/elements/audioiirfilter.c [new file with mode: 0644]
tests/examples/Makefile.am
tests/examples/audiofx/Makefile.am [new file with mode: 0644]
tests/examples/audiofx/firfilter-example.c [new file with mode: 0644]
tests/examples/audiofx/iirfilter-example.c [new file with mode: 0644]

index c336b1f..0aa1a61 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,59 @@
+2009-01-13  Sebastian Dröge  <sebastian.droege@collabora.co.uk>
+
+       * configure.ac:
+       * gst/audiofx/Makefile.am:
+       * gst/audiofx/audiofirfilter.c: (gst_audio_fir_filter_base_init),
+       (gst_audio_fir_filter_class_init),
+       (gst_audio_fir_filter_update_kernel), (gst_audio_fir_filter_init),
+       (gst_audio_fir_filter_setup), (gst_audio_fir_filter_finalize),
+       (gst_audio_fir_filter_set_property),
+       (gst_audio_fir_filter_get_property):
+       * gst/audiofx/audiofirfilter.h:
+       * gst/audiofx/audiofx.c: (plugin_init):
+       * gst/audiofx/audioiirfilter.c: (gst_audio_iir_filter_base_init),
+       (gst_audio_iir_filter_class_init),
+       (gst_audio_iir_filter_update_coefficients),
+       (gst_audio_iir_filter_init), (gst_audio_iir_filter_setup),
+       (gst_audio_iir_filter_finalize),
+       (gst_audio_iir_filter_set_property),
+       (gst_audio_iir_filter_get_property):
+       * gst/audiofx/audioiirfilter.h:
+       Add audioiirfilter and audiofirfilter elements which allow
+       generic IIR/FIR filters to be implemented by providing the
+       filter coefficients. Fixes bug #567577.
+
+       * docs/plugins/Makefile.am:
+       * docs/plugins/gst-plugins-good-plugins-docs.sgml:
+       * docs/plugins/gst-plugins-good-plugins-sections.txt:
+       * docs/plugins/gst-plugins-good-plugins.args:
+       * docs/plugins/gst-plugins-good-plugins.hierarchy:
+       * docs/plugins/gst-plugins-good-plugins.signals:
+       * docs/plugins/inspect/plugin-alaw.xml:
+       * docs/plugins/inspect/plugin-audiofx.xml:
+       * docs/plugins/inspect/plugin-avi.xml:
+       * docs/plugins/inspect/plugin-flac.xml:
+       * docs/plugins/inspect/plugin-mulaw.xml:
+       * docs/plugins/inspect/plugin-video4linux2.xml:
+       * docs/plugins/inspect/plugin-wavparse.xml:
+       Add documentation for the audioiirfilter and audiofirfilter
+       elements.
+
+       * tests/check/Makefile.am:
+       * tests/check/elements/audiofirfilter.c: (on_message),
+       (on_rate_changed), (on_handoff), (GST_START_TEST),
+       (audiofirfilter_suite):
+       * tests/check/elements/audioiirfilter.c: (on_message),
+       (on_rate_changed), (on_handoff), (GST_START_TEST),
+       (audioiirfilter_suite):
+       * tests/examples/Makefile.am:
+       * tests/examples/audiofx/Makefile.am:
+       * tests/examples/audiofx/firfilter-example.c: (on_message),
+       (on_rate_changed), (main):
+       * tests/examples/audiofx/iirfilter-example.c: (on_message),
+       (on_rate_changed), (main):
+       Add unit tests and example applications for the two filter
+       elements.
+
 2009-01-13  Michael Smith <msmith@songbirdnest.com>
 
        Patch by: Thiago Sousa Santos <thiagoss@embedded.ufcg.edu.br>
index 4a9e8ad..f1eaee7 100644 (file)
@@ -1105,6 +1105,7 @@ po/Makefile.in
 tests/Makefile
 tests/check/Makefile
 tests/examples/Makefile
+tests/examples/audiofx/Makefile
 tests/examples/equalizer/Makefile
 tests/examples/level/Makefile
 tests/examples/rtp/Makefile
index f933335..8549ed3 100644 (file)
@@ -112,8 +112,10 @@ EXTRA_HFILES = \
        $(top_srcdir)/gst/audiofx/audiopanorama.h \
        $(top_srcdir)/gst/audiofx/audiocheblimit.h \
        $(top_srcdir)/gst/audiofx/audiochebband.h \
+       $(top_srcdir)/gst/audiofx/audioiirfilter.h \
        $(top_srcdir)/gst/audiofx/audiowsincband.h \
        $(top_srcdir)/gst/audiofx/audiowsinclimit.h \
+       $(top_srcdir)/gst/audiofx/audiofirfilter.h \
        $(top_srcdir)/gst/autodetect/gstautoaudiosink.h \
        $(top_srcdir)/gst/autodetect/gstautoaudiosrc.h \
        $(top_srcdir)/gst/autodetect/gstautovideosink.h \
@@ -177,7 +179,9 @@ EXTRA_HFILES = \
 # example code that needs to be converted to xml and placed in xml/
 EXAMPLE_CFILES = \
        $(top_srcdir)/tests/examples/level/level-example.c \
-       $(top_srcdir)/tests/examples/spectrum/spectrum-example.c
+       $(top_srcdir)/tests/examples/spectrum/spectrum-example.c \
+       $(top_srcdir)/tests/examples/audiofx/firfilter-example.c \
+       $(top_srcdir)/tests/examples/audiofx/iirfilter-example.c
 
 # Images to copy into HTML directory.
 HTML_IMAGES =
index a4bb923..8fedb7f 100644 (file)
     <xi:include href="xml/element-audioamplify.xml" />
     <xi:include href="xml/element-audiochebband.xml" />
     <xi:include href="xml/element-audiocheblimit.xml" />
+    <xi:include href="xml/element-audioiirfilter.xml" />
     <xi:include href="xml/element-audiowsincband.xml" />
     <xi:include href="xml/element-audiowsinclimit.xml" />
+    <xi:include href="xml/element-audiofirfilter.xml" />
     <xi:include href="xml/element-audiodynamic.xml" />
     <xi:include href="xml/element-audioinvert.xml" />
     <xi:include href="xml/element-audiopanorama.xml" />
index b58d7f1..d2de0b0 100644 (file)
@@ -103,6 +103,20 @@ gst_audio_cheb_limit_get_type
 </SECTION>
 
 <SECTION>
+<FILE>element-audioiirfilter</FILE>
+<TITLE>audioiirfilter</TITLE>
+GstAudioIIRFilter
+<SUBSECTION Standard>
+GstAudioIIRFilterClass
+GST_AUDIO_IIR_FILTER
+GST_AUDIO_IIR_FILTER_CLASS
+GST_IS_AUDIO_IIR_FILTER_BAND
+GST_IS_AUDIO_IIR_FILTER_CLASS
+GST_TYPE_AUDIO_IIR_FILTER
+gst_audio_iir_filter_get_type
+</SECTION>
+
+<SECTION>
 <FILE>element-audiodynamic</FILE>
 <TITLE>audiodynamic</TITLE>
 GstAudioDynamic
@@ -178,7 +192,7 @@ GST_AUDIO_WSINC_BAND_CLASS
 GST_IS_AUDIO_WSINC_BAND
 GST_IS_AUDIO_WSINC_BAND_CLASS
 GST_TYPE_AUDIO_WSINC_BAND
-audio_wsincband_get_type
+gst_audio_wsincband_get_type
 </SECTION>
 
 <SECTION>
@@ -193,7 +207,21 @@ GST_AUDIO_WSINC_LIMIT_CLASS
 GST_IS_AUDIO_WSINC_LIMIT
 GST_IS_AUDIO_WSINC_LIMIT_CLASS
 GST_TYPE_AUDIO_WSINC_LIMIT
-audio_wsinclimit_get_type
+gst_audio_wsinclimit_get_type
+</SECTION>
+
+<SECTION>
+<FILE>element-audiofirfilter</FILE>
+<TITLE>audiofirfilter</TITLE>
+GstAudioFIRFilter
+<SUBSECTION Standard>
+GstAudioFIRFilterClass
+GST_AUDIO_FIR_FILTER
+GST_AUDIO_FIR_FILTER_CLASS
+GST_IS_AUDIO_FIR_FILTER_BAND
+GST_IS_AUDIO_FIR_FILTER_CLASS
+GST_TYPE_AUDIO_FIR_FILTER
+gst_audio_fir_filter_get_type
 </SECTION>
 
 <SECTION>
index a412fa0..0064b66 100644 (file)
 <DEFAULT>1</DEFAULT>
 </ARG>
 
+<ARG>
+<NAME>GstAudioFIRFilter::kernel</NAME>
+<TYPE>GValueArray*</TYPE>
+<RANGE></RANGE>
+<FLAGS>rw</FLAGS>
+<NICK>Filter Kernel</NICK>
+<BLURB>Filter kernel for the FIR filter.</BLURB>
+<DEFAULT></DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstAudioFIRFilter::latency</NAME>
+<TYPE>guint64</TYPE>
+<RANGE></RANGE>
+<FLAGS>rw</FLAGS>
+<NICK>Latecy</NICK>
+<BLURB>Filter latency in samples.</BLURB>
+<DEFAULT>0</DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstAudioIIRFilter::a</NAME>
+<TYPE>GValueArray*</TYPE>
+<RANGE></RANGE>
+<FLAGS>rw</FLAGS>
+<NICK>A</NICK>
+<BLURB>Filter coefficients (numerator of transfer function).</BLURB>
+<DEFAULT></DEFAULT>
+</ARG>
+
+<ARG>
+<NAME>GstAudioIIRFilter::b</NAME>
+<TYPE>GValueArray*</TYPE>
+<RANGE></RANGE>
+<FLAGS>rw</FLAGS>
+<NICK>B</NICK>
+<BLURB>Filter coefficients (denominator of transfer function).</BLURB>
+<DEFAULT></DEFAULT>
+</ARG>
+
index 8367c0c..55e1cdc 100644 (file)
@@ -56,10 +56,14 @@ GObject
           GstAudioKaraoke
           GstAudioAmplify
           GstAudioDynamic
-          GstAudioChebLimit
-          GstAudioChebBand
-          GstAudioWSincLimit
-          GstAudioWSincBand
+          GstAudioFXBaseIIRFilter
+            GstAudioChebLimit
+            GstAudioChebBand
+            GstAudioIIRFilter
+          GstAudioFXBaseFIRFilter
+            GstAudioWSincLimit
+            GstAudioWSincBand
+            GstAudioFIRFilter
           GstIirEqualizer
             GstIirEqualizerNBands
             GstIirEqualizer3Bands
index cc7792d..94c1e54 100644 (file)
@@ -332,3 +332,19 @@ guint  arg1
 guint  arg2
 </SIGNAL>
 
+<SIGNAL>
+<NAME>GstAudioFIRFilter::rate-changed</NAME>
+<RETURNS>void</RETURNS>
+<FLAGS>l</FLAGS>
+GstAudioFIRFilter *gstaudiofirfilter
+gint  arg1
+</SIGNAL>
+
+<SIGNAL>
+<NAME>GstAudioIIRFilter::rate-changed</NAME>
+<RETURNS>void</RETURNS>
+<FLAGS>l</FLAGS>
+GstAudioIIRFilter *gstaudioiirfilter
+gint  arg1
+</SIGNAL>
+
index a47915a..509d89b 100644 (file)
@@ -26,7 +26,7 @@
           <name>src</name>
           <direction>source</direction>
           <presence>always</presence>
-          <details>audio/x-raw-int, width=(int)16, depth=(int)16, endianness=(int)1234, signed=(boolean)true, rate=(int)[ 8000, 192000 ], channels=(int)[ 1, 2 ]</details>
+          <details>audio/x-raw-int, rate=(int)[ 8000, 192000 ], channels=(int)[ 1, 2 ], endianness=(int)1234, width=(int)16, signed=(boolean)true</details>
         </caps>
       </pads>
     </element>
@@ -41,7 +41,7 @@
           <name>sink</name>
           <direction>sink</direction>
           <presence>always</presence>
-          <details>audio/x-raw-int, width=(int)16, depth=(int)16, endianness=(int)1234, signed=(boolean)true, rate=(int)[ 8000, 192000 ], channels=(int)[ 1, 2 ]</details>
+          <details>audio/x-raw-int, rate=(int)[ 8000, 192000 ], channels=(int)[ 1, 2 ], endianness=(int)1234, width=(int)16, signed=(boolean)true</details>
         </caps>
         <caps>
           <name>src</name>
index 939c220..7ca2add 100644 (file)
@@ -35,7 +35,7 @@
       <longname>Band pass &amp; band reject filter</longname>
       <class>Filter/Effect/Audio</class>
       <description>Chebyshev band pass and band reject filter</description>
-      <author>Sebastian Dröge &lt;slomo@circular-chaos.org&gt;</author>
+      <author>Sebastian Dröge &lt;sebastian.droege@collabora.co.uk&gt;</author>
       <pads>
         <caps>
           <name>sink</name>
@@ -56,7 +56,7 @@
       <longname>Low pass &amp; high pass filter</longname>
       <class>Filter/Effect/Audio</class>
       <description>Chebyshev low pass and high pass filter</description>
-      <author>Sebastian Dröge &lt;slomo@circular-chaos.org&gt;</author>
+      <author>Sebastian Dröge &lt;sebastian.droege@collabora.co.uk&gt;</author>
       <pads>
         <caps>
           <name>sink</name>
       </pads>
     </element>
     <element>
+      <name>audiofirfilter</name>
+      <longname>Audio FIR filter</longname>
+      <class>Filter/Effect/Audio</class>
+      <description>Generic audio FIR filter with custom filter kernel</description>
+      <author>Sebastian Dröge &lt;sebastian.droege@collabora.co.uk&gt;</author>
+      <pads>
+        <caps>
+          <name>sink</name>
+          <direction>sink</direction>
+          <presence>always</presence>
+          <details>audio/x-raw-float, width=(int){ 32, 64 }, endianness=(int)1234, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ]</details>
+        </caps>
+        <caps>
+          <name>src</name>
+          <direction>source</direction>
+          <presence>always</presence>
+          <details>audio/x-raw-float, width=(int){ 32, 64 }, endianness=(int)1234, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ]</details>
+        </caps>
+      </pads>
+    </element>
+    <element>
+      <name>audioiirfilter</name>
+      <longname>Audio IIR filter</longname>
+      <class>Filter/Effect/Audio</class>
+      <description>Generic audio IIR filter with custom filter kernel</description>
+      <author>Sebastian Dröge &lt;sebastian.droege@collabora.co.uk&gt;</author>
+      <pads>
+        <caps>
+          <name>sink</name>
+          <direction>sink</direction>
+          <presence>always</presence>
+          <details>audio/x-raw-float, width=(int){ 32, 64 }, endianness=(int)1234, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ]</details>
+        </caps>
+        <caps>
+          <name>src</name>
+          <direction>source</direction>
+          <presence>always</presence>
+          <details>audio/x-raw-float, width=(int){ 32, 64 }, endianness=(int)1234, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ]</details>
+        </caps>
+      </pads>
+    </element>
+    <element>
       <name>audioinvert</name>
       <longname>Audio inversion</longname>
       <class>Filter/Effect/Audio</class>
       <longname>Band pass &amp; band reject filter</longname>
       <class>Filter/Effect/Audio</class>
       <description>Band pass and band reject windowed sinc filter</description>
-      <author>Thomas Vander Stichele &lt;thomas at apestaart dot org&gt;, Steven W. Smith, Dreamlab Technologies Ltd. &lt;mathis.hofer@dreamlab.net&gt;, Sebastian Dröge &lt;slomo@circular-chaos.org&gt;</author>
+      <author>Thomas Vander Stichele &lt;thomas at apestaart dot org&gt;, Steven W. Smith, Dreamlab Technologies Ltd. &lt;mathis.hofer@dreamlab.net&gt;, Sebastian Dröge &lt;sebastian.droege@collabora.co.uk&gt;</author>
       <pads>
         <caps>
           <name>sink</name>
       <longname>Low pass &amp; high pass filter</longname>
       <class>Filter/Effect/Audio</class>
       <description>Low pass and high pass windowed sinc filter</description>
-      <author>Thomas Vander Stichele &lt;thomas at apestaart dot org&gt;, Steven W. Smith, Dreamlab Technologies Ltd. &lt;mathis.hofer@dreamlab.net&gt;, Sebastian Dröge &lt;slomo@circular-chaos.org&gt;</author>
+      <author>Thomas Vander Stichele &lt;thomas at apestaart dot org&gt;, Steven W. Smith, Dreamlab Technologies Ltd. &lt;mathis.hofer@dreamlab.net&gt;, Sebastian Dröge &lt;sebastian.droege@collabora.co.uk&gt;</author>
       <pads>
         <caps>
           <name>sink</name>
index 3cb4515..5000007 100644 (file)
           <name>video_%02d</name>
           <direction>source</direction>
           <presence>sometimes</presence>
-          <details>video/x-3ivx, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-asus, asusversion=(int)1, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-asus, asusversion=(int)2, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-cirrus-logic-accupak, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-compressed-yuv, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-raw-rgb, bpp=(int){ 8, 24 }, depth=(int){ 8, 24 }, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-divx, divxversion=(int)3, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-divx, divxversion=(int)4, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-truemotion, trueversion=(int)1, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-dv, systemstream=(boolean)false, dvversion=(int)25, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-dv, systemstream=(boolean)false, dvversion=(int)50, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-divx, divxversion=(int)5, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-flash-video, flvversion=(int)1, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-h263, variant=(string)itu, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-h264, variant=(string)itu, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-huffyuv, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-intel-h263, variant=(string)intel, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-raw-yuv, format=(fourcc)I420, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-indeo, indeoversion=(int)3, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-indeo, indeoversion=(int)4, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-indeo, indeoversion=(int)5, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-h263, variant=(string)lead, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-h264, variant=(string)lead, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-h263, variant=(string)microsoft, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/mpeg, mpegversion=(int)4, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; image/jpeg, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-msmpeg, msmpegversion=(int)42, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-msmpeg, msmpegversion=(int)43, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/mpeg, systemstream=(boolean)false, mpegversion=(int)1, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/mpeg, systemstream=(boolean)false, mpegversion=(int)2, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-msmpeg, msmpegversion=(int)41, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-mszh, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; image/png, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-rle, layout=(string)microsoft, depth=(int)[ 1, 64 ], framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-indeo, indeoversion=(int)2, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/sp5x, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-truemotion, trueversion=(int)2, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-camtasia, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-ultimotion, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-ati-vcr, vcrversion=(int)1, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-ati-vcr, vcrversion=(int)2, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-h263, variant=(string)vdolive, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-h263, variant=(string)vivo, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-vmnc, version=(int)1, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-vp3, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-h264, variant=(string)videosoft, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-wmv, wmvversion=(int)1, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-wmv, wmvversion=(int)2, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-wmv, wmvversion=(int)3, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-xvid, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-xan, wcversion=(int)4, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-raw-yuv, format=(fourcc)YUY2, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-raw-yuv, format=(fourcc)YVU9, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-zlib, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-cinepak, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-h264, variant=(string)itu, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-msvideocodec, msvideoversion=(int)1, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-h263, variant=(string)xirlink, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-dirac, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-ffv, ffvversion=(int)1, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-kmvc, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-dv, systemstream=(boolean)true; video/x-avi-unknown</details>
+          <details>video/x-3ivx, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-asus, asusversion=(int)1, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-asus, asusversion=(int)2, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-cirrus-logic-accupak, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-compressed-yuv, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-raw-rgb, bpp=(int){ 8, 24 }, depth=(int){ 8, 24 }, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-divx, divxversion=(int)3, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-divx, divxversion=(int)4, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-truemotion, trueversion=(int)1, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-dv, systemstream=(boolean)false, dvversion=(int)25, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-dv, systemstream=(boolean)false, dvversion=(int)50, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-divx, divxversion=(int)5, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-flash-video, flvversion=(int)1, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-h263, variant=(string)itu, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-h264, variant=(string)itu, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-huffyuv, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-intel-h263, variant=(string)intel, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-raw-yuv, format=(fourcc)I420, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-indeo, indeoversion=(int)3, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-indeo, indeoversion=(int)4, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-indeo, indeoversion=(int)5, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-h263, variant=(string)lead, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-h264, variant=(string)lead, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-h263, variant=(string)microsoft, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/mpeg, mpegversion=(int)4, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; image/jpeg, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-msmpeg, msmpegversion=(int)42, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-msmpeg, msmpegversion=(int)43, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/mpeg, systemstream=(boolean)false, mpegversion=(int)1, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/mpeg, systemstream=(boolean)false, mpegversion=(int)2, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-msmpeg, msmpegversion=(int)41, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-mszh, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; image/png, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-rle, layout=(string)microsoft, depth=(int)[ 1, 64 ], framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-indeo, indeoversion=(int)2, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/sp5x, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-truemotion, trueversion=(int)2, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-camtasia, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-ultimotion, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-ati-vcr, vcrversion=(int)1, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-ati-vcr, vcrversion=(int)2, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-h263, variant=(string)vdolive, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-h263, variant=(string)vivo, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-vmnc, version=(int)1, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-vp3, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-h264, variant=(string)videosoft, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-wmv, wmvversion=(int)1, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-wmv, wmvversion=(int)2, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-wmv, wmvversion=(int)3, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-xvid, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-xan, wcversion=(int)4, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-raw-yuv, format=(fourcc)YUY2, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-raw-yuv, format=(fourcc)YVU9, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-zlib, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-cinepak, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-h264, variant=(string)itu, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-msvideocodec, msvideoversion=(int)1, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-h263, variant=(string)xirlink, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-dirac, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-ffv, ffvversion=(int)1, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-kmvc, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-vp6, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-dv, systemstream=(boolean)true; video/x-avi-unknown</details>
         </caps>
         <caps>
           <name>audio_%02d</name>
           <direction>source</direction>
           <presence>sometimes</presence>
-          <details>audio/ms-gsm, rate=(int)[ 1, 96000 ], channels=(int)[ 1, 2 ]; audio/mpeg, mpegversion=(int)1, layer=(int)3, rate=(int)[ 8000, 48000 ], channels=(int)[ 1, 2 ]; audio/mpeg, mpegversion=(int)1, layer=(int)2, rate=(int)[ 16000, 48000 ], channels=(int)[ 1, 2 ]; audio/x-raw-int, endianness=(int)1234, signed=(boolean){ true, false }, width=(int){ 8, 16, 24, 32 }, depth=(int)[ 1, 32 ], rate=(int)[ 1000, 96000 ], channels=(int)[ 1, 8 ]; audio/x-vorbis, rate=(int)[ 1000, 96000 ], channels=(int)[ 1, 2 ]; audio/x-ac3, rate=(int)[ 1000, 96000 ], channels=(int)[ 1, 6 ]; audio/x-dts; audio/mpeg, mpegversion=(int)4, rate=(int)[ 1000, 96000 ], channels=(int)[ 1, 8 ]; audio/x-alaw, rate=(int)[ 1000, 48000 ], channels=(int)[ 1, 2 ]; audio/x-mulaw, rate=(int)[ 1000, 48000 ], channels=(int)[ 1, 2 ]; audio/x-wms, bitrate=(int)[ 0, 2147483647 ], rate=(int)[ 1000, 96000 ], channels=(int)[ 1, 2 ], block_align=(int)[ 1, 2147483647 ]; audio/x-adpcm, layout=(string)microsoft, rate=(int)[ 1000, 96000 ], channels=(int)[ 1, 2 ], block_align=(int)[ 1, 2147483647 ]; audio/x-adpcm, layout=(string)dvi, rate=(int)[ 1000, 48000 ], channels=(int)[ 1, 2 ], block_align=(int)[ 1, 2147483647 ]; audio/x-truespeech, rate=(int)8000, channels=(int)[ 1, 2 ]; audio/x-wma, wmaversion=(int)1, bitrate=(int)[ 0, 2147483647 ], rate=(int)[ 1000, 96000 ], channels=(int)[ 1, 6 ], block_align=(int)[ 1, 2147483647 ]; audio/x-wma, wmaversion=(int)2, bitrate=(int)[ 0, 2147483647 ], rate=(int)[ 1000, 96000 ], channels=(int)[ 1, 6 ], block_align=(int)[ 1, 2147483647 ]; audio/x-wma, wmaversion=(int)3, bitrate=(int)[ 0, 2147483647 ], rate=(int)[ 1000, 96000 ], channels=(int)[ 1, 6 ], block_align=(int)[ 1, 2147483647 ]; audio/x-vnd.sony.atrac3, rate=(int)[ 1000, 96000 ], channels=(int)[ 1, 2 ]; audio/x-raw-float, endianness=(int)1234, width=(int){ 32, 64 }, rate=(int)[ 1000, 96000 ], channels=(int)[ 1, 8 ]; audio/x-voxware, voxwaretype=(int)117, rate=(int)[ 1000, 96000 ], channels=(int)[ 1, 2 ]; audio/x-adpcm, layout=(string)dk4, rate=(int)[ 8000, 96000 ], channels=(int)[ 1, 2 ]; audio/x-adpcm, layout=(string)dk3, rate=(int)[ 8000, 96000 ], channels=(int)[ 1, 2 ]; application/x-ogg-avi; audio/x-avi-unknown</details>
+          <details>audio/ms-gsm, rate=(int)[ 1, 96000 ], channels=(int)[ 1, 2 ]; audio/mpeg, mpegversion=(int)1, layer=(int)3, rate=(int)[ 8000, 48000 ], channels=(int)[ 1, 2 ]; audio/mpeg, mpegversion=(int)1, layer=(int)2, rate=(int)[ 16000, 48000 ], channels=(int)[ 1, 2 ]; audio/x-raw-int, endianness=(int)1234, signed=(boolean){ true, false }, width=(int){ 8, 16, 24, 32 }, depth=(int)[ 1, 32 ], rate=(int)[ 1000, 192000 ], channels=(int)[ 1, 8 ]; audio/x-vorbis, rate=(int)[ 1000, 192000 ], channels=(int)[ 1, 2 ]; audio/x-ac3, rate=(int)[ 1000, 96000 ], channels=(int)[ 1, 6 ]; audio/x-dts; audio/mpeg, mpegversion=(int)4, rate=(int)[ 1000, 96000 ], channels=(int)[ 1, 8 ]; audio/x-alaw, rate=(int)[ 1000, 48000 ], channels=(int)[ 1, 2 ]; audio/x-mulaw, rate=(int)[ 1000, 48000 ], channels=(int)[ 1, 2 ]; audio/x-wms, bitrate=(int)[ 0, 2147483647 ], rate=(int)[ 1000, 96000 ], channels=(int)[ 1, 2 ], block_align=(int)[ 1, 2147483647 ]; audio/x-adpcm, layout=(string)microsoft, rate=(int)[ 1000, 96000 ], channels=(int)[ 1, 2 ], block_align=(int)[ 1, 2147483647 ]; audio/x-adpcm, layout=(string)dvi, rate=(int)[ 1000, 48000 ], channels=(int)[ 1, 2 ], block_align=(int)[ 1, 2147483647 ]; audio/x-truespeech, rate=(int)8000, channels=(int)[ 1, 2 ]; audio/x-wma, wmaversion=(int)1, bitrate=(int)[ 0, 2147483647 ], rate=(int)[ 1000, 96000 ], channels=(int)[ 1, 6 ], block_align=(int)[ 1, 2147483647 ]; audio/x-wma, wmaversion=(int)2, bitrate=(int)[ 0, 2147483647 ], rate=(int)[ 1000, 96000 ], channels=(int)[ 1, 6 ], block_align=(int)[ 1, 2147483647 ]; audio/x-wma, wmaversion=(int)3, bitrate=(int)[ 0, 2147483647 ], rate=(int)[ 1000, 96000 ], channels=(int)[ 1, 6 ], block_align=(int)[ 1, 2147483647 ]; audio/x-vnd.sony.atrac3, rate=(int)[ 1000, 96000 ], channels=(int)[ 1, 2 ]; audio/x-raw-float, endianness=(int)1234, width=(int){ 32, 64 }, rate=(int)[ 1000, 192000 ], channels=(int)[ 1, 8 ]; audio/x-voxware, voxwaretype=(int)117, rate=(int)[ 1000, 96000 ], channels=(int)[ 1, 2 ]; audio/x-adpcm, layout=(string)dk4, rate=(int)[ 8000, 96000 ], channels=(int)[ 1, 2 ]; audio/x-adpcm, layout=(string)dk3, rate=(int)[ 8000, 96000 ], channels=(int)[ 1, 2 ]; application/x-ogg-avi; audio/x-avi-unknown</details>
         </caps>
       </pads>
     </element>
index 318d1c9..cd8c587 100644 (file)
       <author>Wim Taymans &lt;wim@fluendo.com&gt;</author>
       <pads>
         <caps>
-          <name>src</name>
-          <direction>source</direction>
-          <presence>always</presence>
-          <details>audio/x-raw-int, endianness=(int)1234, signed=(boolean)true, width=(int){ 8, 16, 32 }, depth=(int)[ 4, 32 ], rate=(int)[ 1, 655350 ], channels=(int)[ 1, 8 ]</details>
-        </caps>
-        <caps>
           <name>sink</name>
           <direction>sink</direction>
           <presence>always</presence>
           <details>audio/x-flac</details>
         </caps>
+        <caps>
+          <name>src</name>
+          <direction>source</direction>
+          <presence>always</presence>
+          <details>audio/x-raw-int, endianness=(int)1234, signed=(boolean)true, width=(int){ 8, 16, 32 }, depth=(int)[ 4, 32 ], rate=(int)[ 1, 655350 ], channels=(int)[ 1, 8 ]</details>
+        </caps>
       </pads>
     </element>
     <element>
index 5f1d304..8be885b 100644 (file)
@@ -26,7 +26,7 @@
           <name>src</name>
           <direction>source</direction>
           <presence>always</presence>
-          <details>audio/x-raw-int, width=(int)16, depth=(int)16, endianness=(int)1234, signed=(boolean)true, rate=(int)[ 8000, 192000 ], channels=(int)[ 1, 2 ]</details>
+          <details>audio/x-raw-int, rate=(int)[ 8000, 192000 ], channels=(int)[ 1, 2 ], endianness=(int)1234, width=(int)16, signed=(boolean)true</details>
         </caps>
       </pads>
     </element>
@@ -41,7 +41,7 @@
           <name>sink</name>
           <direction>sink</direction>
           <presence>always</presence>
-          <details>audio/x-raw-int, width=(int)16, depth=(int)16, endianness=(int)1234, signed=(boolean)true, rate=(int)[ 8000, 192000 ], channels=(int)[ 1, 2 ]</details>
+          <details>audio/x-raw-int, rate=(int)[ 8000, 192000 ], channels=(int)[ 1, 2 ], endianness=(int)1234, width=(int)16, signed=(boolean)true</details>
         </caps>
         <caps>
           <name>src</name>
index 25fb780..bb5c62f 100644 (file)
@@ -20,7 +20,7 @@
           <name>src</name>
           <direction>source</direction>
           <presence>always</presence>
-          <details>video/x-raw-rgb, bpp=(int)8, depth=(int)8, red_mask=(int)224, green_mask=(int)28, blue_mask=(int)3, endianness=(int)1234, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-rgb, bpp=(int)16, depth=(int)15, red_mask=(int)31744, green_mask=(int)992, blue_mask=(int)31, endianness=(int)1234, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-rgb, bpp=(int)16, depth=(int)16, red_mask=(int)63488, green_mask=(int)2016, blue_mask=(int)31, endianness=(int)1234, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-rgb, bpp=(int)16, depth=(int)15, red_mask=(int)31744, green_mask=(int)992, blue_mask=(int)31, endianness=(int)4321, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-rgb, bpp=(int)16, depth=(int)16, red_mask=(int)63488, green_mask=(int)2016, blue_mask=(int)31, endianness=(int)4321, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-rgb, bpp=(int)24, depth=(int)24, red_mask=(int)255, green_mask=(int)65280, blue_mask=(int)16711680, endianness=(int)4321, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-rgb, bpp=(int)24, depth=(int)24, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, endianness=(int)4321, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, red_mask=(int)255, green_mask=(int)65280, blue_mask=(int)16711680, endianness=(int)4321, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, red_mask=(int)-16777216, green_mask=(int)16711680, blue_mask=(int)65280, endianness=(int)4321, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-yuv, format=(fourcc)YVU9, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-yuv, format=(fourcc)YV12, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-yuv, format=(fourcc)YUY2, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-yuv, format=(fourcc)UYVY, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-yuv, format=(fourcc)Y42B, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-yuv, format=(fourcc)Y41B, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-yuv, format=(fourcc)Y41P, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-yuv, format=(fourcc)NV12, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-yuv, format=(fourcc)NV21, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-yuv, format=(fourcc)YUV9, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-yuv, format=(fourcc)I420, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-bayer, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; image/jpeg, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; image/jpeg, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-dv, systemstream=(boolean)true, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-sonix, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-pwc1, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-pwc2, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]</details>
+          <details>video/x-raw-rgb, bpp=(int)8, depth=(int)8, red_mask=(int)224, green_mask=(int)28, blue_mask=(int)3, endianness=(int)1234, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-rgb, bpp=(int)16, depth=(int)15, red_mask=(int)31744, green_mask=(int)992, blue_mask=(int)31, endianness=(int)1234, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-rgb, bpp=(int)16, depth=(int)16, red_mask=(int)63488, green_mask=(int)2016, blue_mask=(int)31, endianness=(int)1234, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-rgb, bpp=(int)16, depth=(int)15, red_mask=(int)31744, green_mask=(int)992, blue_mask=(int)31, endianness=(int)4321, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-rgb, bpp=(int)16, depth=(int)16, red_mask=(int)63488, green_mask=(int)2016, blue_mask=(int)31, endianness=(int)4321, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-rgb, bpp=(int)24, depth=(int)24, red_mask=(int)255, green_mask=(int)65280, blue_mask=(int)16711680, endianness=(int)4321, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-rgb, bpp=(int)24, depth=(int)24, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, endianness=(int)4321, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, red_mask=(int)255, green_mask=(int)65280, blue_mask=(int)16711680, endianness=(int)4321, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, red_mask=(int)-16777216, green_mask=(int)16711680, blue_mask=(int)65280, endianness=(int)4321, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-gray, bpp=(int)8, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-yuv, format=(fourcc)YVU9, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-yuv, format=(fourcc)YV12, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-yuv, format=(fourcc)YUY2, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-yuv, format=(fourcc)UYVY, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-yuv, format=(fourcc)Y42B, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-yuv, format=(fourcc)Y41B, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-yuv, format=(fourcc)Y41P, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-yuv, format=(fourcc)NV12, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-yuv, format=(fourcc)NV21, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-yuv, format=(fourcc)YUV9, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-yuv, format=(fourcc)I420, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-raw-bayer, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; image/jpeg, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; image/jpeg, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-dv, systemstream=(boolean)true, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-sonix, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-pwc1, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]; video/x-pwc2, width=(int)[ 1, 32768 ], height=(int)[ 1, 32768 ], framerate=(fraction)[ 0/1, 100/1 ]</details>
         </caps>
       </pads>
     </element>
index e1dfbc9..2ca9d18 100644 (file)
@@ -20,7 +20,7 @@
           <name>wavparse_src</name>
           <direction>source</direction>
           <presence>sometimes</presence>
-          <details>audio/ms-gsm, rate=(int)[ 1, 96000 ], channels=(int)[ 1, 2 ]; audio/mpeg, mpegversion=(int)1, layer=(int)3, rate=(int)[ 8000, 48000 ], channels=(int)[ 1, 2 ]; audio/mpeg, mpegversion=(int)1, layer=(int)2, rate=(int)[ 16000, 48000 ], channels=(int)[ 1, 2 ]; audio/x-raw-int, endianness=(int)1234, signed=(boolean){ true, false }, width=(int){ 8, 16, 24, 32 }, depth=(int)[ 1, 32 ], rate=(int)[ 1000, 96000 ], channels=(int)[ 1, 8 ]; audio/x-vorbis, rate=(int)[ 1000, 96000 ], channels=(int)[ 1, 2 ]; audio/x-ac3, rate=(int)[ 1000, 96000 ], channels=(int)[ 1, 6 ]; audio/x-dts; audio/mpeg, mpegversion=(int)4, rate=(int)[ 1000, 96000 ], channels=(int)[ 1, 8 ]; audio/x-alaw, rate=(int)[ 1000, 48000 ], channels=(int)[ 1, 2 ]; audio/x-mulaw, rate=(int)[ 1000, 48000 ], channels=(int)[ 1, 2 ]; audio/x-wms, bitrate=(int)[ 0, 2147483647 ], rate=(int)[ 1000, 96000 ], channels=(int)[ 1, 2 ], block_align=(int)[ 1, 2147483647 ]; audio/x-adpcm, layout=(string)microsoft, rate=(int)[ 1000, 96000 ], channels=(int)[ 1, 2 ], block_align=(int)[ 1, 2147483647 ]; audio/x-adpcm, layout=(string)dvi, rate=(int)[ 1000, 48000 ], channels=(int)[ 1, 2 ], block_align=(int)[ 1, 2147483647 ]; audio/x-truespeech, rate=(int)8000, channels=(int)[ 1, 2 ]; audio/x-wma, wmaversion=(int)1, bitrate=(int)[ 0, 2147483647 ], rate=(int)[ 1000, 96000 ], channels=(int)[ 1, 6 ], block_align=(int)[ 1, 2147483647 ]; audio/x-wma, wmaversion=(int)2, bitrate=(int)[ 0, 2147483647 ], rate=(int)[ 1000, 96000 ], channels=(int)[ 1, 6 ], block_align=(int)[ 1, 2147483647 ]; audio/x-wma, wmaversion=(int)3, bitrate=(int)[ 0, 2147483647 ], rate=(int)[ 1000, 96000 ], channels=(int)[ 1, 6 ], block_align=(int)[ 1, 2147483647 ]; audio/x-vnd.sony.atrac3, rate=(int)[ 1000, 96000 ], channels=(int)[ 1, 2 ]; audio/x-raw-float, endianness=(int)1234, width=(int){ 32, 64 }, rate=(int)[ 1000, 96000 ], channels=(int)[ 1, 8 ]; audio/x-voxware, voxwaretype=(int)117, rate=(int)[ 1000, 96000 ], channels=(int)[ 1, 2 ]; audio/x-adpcm, layout=(string)dk4, rate=(int)[ 8000, 96000 ], channels=(int)[ 1, 2 ]; audio/x-adpcm, layout=(string)dk3, rate=(int)[ 8000, 96000 ], channels=(int)[ 1, 2 ]; application/x-ogg-avi</details>
+          <details>audio/ms-gsm, rate=(int)[ 1, 96000 ], channels=(int)[ 1, 2 ]; audio/mpeg, mpegversion=(int)1, layer=(int)3, rate=(int)[ 8000, 48000 ], channels=(int)[ 1, 2 ]; audio/mpeg, mpegversion=(int)1, layer=(int)2, rate=(int)[ 16000, 48000 ], channels=(int)[ 1, 2 ]; audio/x-raw-int, endianness=(int)1234, signed=(boolean){ true, false }, width=(int){ 8, 16, 24, 32 }, depth=(int)[ 1, 32 ], rate=(int)[ 1000, 192000 ], channels=(int)[ 1, 8 ]; audio/x-vorbis, rate=(int)[ 1000, 192000 ], channels=(int)[ 1, 2 ]; audio/x-ac3, rate=(int)[ 1000, 96000 ], channels=(int)[ 1, 6 ]; audio/x-dts; audio/mpeg, mpegversion=(int)4, rate=(int)[ 1000, 96000 ], channels=(int)[ 1, 8 ]; audio/x-alaw, rate=(int)[ 1000, 48000 ], channels=(int)[ 1, 2 ]; audio/x-mulaw, rate=(int)[ 1000, 48000 ], channels=(int)[ 1, 2 ]; audio/x-wms, bitrate=(int)[ 0, 2147483647 ], rate=(int)[ 1000, 96000 ], channels=(int)[ 1, 2 ], block_align=(int)[ 1, 2147483647 ]; audio/x-adpcm, layout=(string)microsoft, rate=(int)[ 1000, 96000 ], channels=(int)[ 1, 2 ], block_align=(int)[ 1, 2147483647 ]; audio/x-adpcm, layout=(string)dvi, rate=(int)[ 1000, 48000 ], channels=(int)[ 1, 2 ], block_align=(int)[ 1, 2147483647 ]; audio/x-truespeech, rate=(int)8000, channels=(int)[ 1, 2 ]; audio/x-wma, wmaversion=(int)1, bitrate=(int)[ 0, 2147483647 ], rate=(int)[ 1000, 96000 ], channels=(int)[ 1, 6 ], block_align=(int)[ 1, 2147483647 ]; audio/x-wma, wmaversion=(int)2, bitrate=(int)[ 0, 2147483647 ], rate=(int)[ 1000, 96000 ], channels=(int)[ 1, 6 ], block_align=(int)[ 1, 2147483647 ]; audio/x-wma, wmaversion=(int)3, bitrate=(int)[ 0, 2147483647 ], rate=(int)[ 1000, 96000 ], channels=(int)[ 1, 6 ], block_align=(int)[ 1, 2147483647 ]; audio/x-vnd.sony.atrac3, rate=(int)[ 1000, 96000 ], channels=(int)[ 1, 2 ]; audio/x-raw-float, endianness=(int)1234, width=(int){ 32, 64 }, rate=(int)[ 1000, 192000 ], channels=(int)[ 1, 8 ]; audio/x-voxware, voxwaretype=(int)117, rate=(int)[ 1000, 96000 ], channels=(int)[ 1, 2 ]; audio/x-adpcm, layout=(string)dk4, rate=(int)[ 8000, 96000 ], channels=(int)[ 1, 2 ]; audio/x-adpcm, layout=(string)dk3, rate=(int)[ 8000, 96000 ], channels=(int)[ 1, 2 ]; application/x-ogg-avi</details>
         </caps>
         <caps>
           <name>wavparse_sink</name>
index d93d3e9..0ba4f1f 100644 (file)
@@ -12,9 +12,11 @@ libgstaudiofx_la_SOURCES = audiofx.c\
        audiofxbaseiirfilter.c \
        audiocheblimit.c \
        audiochebband.c \
+       audioiirfilter.c \
        audiofxbasefirfilter.c \
        audiowsincband.c \
-       audiowsinclimit.c
+       audiowsinclimit.c \
+       audiofirfilter.c
 
 # flags used to compile this plugin
 libgstaudiofx_la_CFLAGS = $(GST_CFLAGS) \
@@ -39,8 +41,10 @@ noinst_HEADERS = audiopanorama.h \
        audiofxbaseiirfilter.h \
        audiocheblimit.h \
        audiochebband.h \
+       audioiirfilter.h \
        audiofxbasefirfilter.h \
        audiowsincband.h \
         audiowsinclimit.h \
+       audiofirfilter.h \
        math_compat.h
 
diff --git a/gst/audiofx/audiofirfilter.c b/gst/audiofx/audiofirfilter.c
new file mode 100644 (file)
index 0000000..3ee4d83
--- /dev/null
@@ -0,0 +1,273 @@
+/* 
+ * GStreamer
+ * Copyright (C) 2009 Sebastian Dröge <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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ * 
+ */
+
+/**
+ * SECTION:element-audiofirfilter
+ * @short_description: Generic audio FIR filter
+ *
+ * <refsect2>
+ * <para>
+ * audiofirfilter implements a generic audio <ulink url="http://en.wikipedia.org/wiki/Finite_impulse_response">FIR filter</ulink>. Before usage the
+ * "kernel" property has to be set to the filter kernel that should be
+ * used and the "latency" property has to be set to the latency (in samples)
+ * that is introduced by the filter kernel. Setting a latency of n samples
+ * will lead to the first n samples being dropped from the output and
+ * n samples added to the end.
+ * </para>
+ * <para>
+ * The filter kernel describes the impulse response of the filter. To
+ * calculate the frequency response of the filter you have to calculate
+ * the Fourier Transform of the impulse response.
+ * </para>
+ * <para>
+ * To change the filter kernel whenever the sampling rate changes the
+ * "rate-changed" signal can be used. This should be done for most
+ * FIR filters as they're depending on the sampling rate.
+ * </para>
+ * <title>Example application</title>
+ * <para>
+ * <include xmlns="http://www.w3.org/2003/XInclude" href="element-firfilter-example.xml" />
+ * </para>
+ * </refsect2>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include <math.h>
+#include <gst/gst.h>
+#include <gst/audio/gstaudiofilter.h>
+#include <gst/controller/gstcontroller.h>
+
+#include "audiofirfilter.h"
+
+#define GST_CAT_DEFAULT gst_audio_fir_filter_debug
+GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
+
+enum
+{
+  SIGNAL_RATE_CHANGED,
+  LAST_SIGNAL
+};
+
+enum
+{
+  PROP_0,
+  PROP_KERNEL,
+  PROP_LATENCY
+};
+
+static guint gst_audio_fir_filter_signals[LAST_SIGNAL] = { 0, };
+
+#define DEBUG_INIT(bla) \
+  GST_DEBUG_CATEGORY_INIT (gst_audio_fir_filter_debug, "audiofirfilter", 0, \
+      "Generic audio FIR filter plugin");
+
+GST_BOILERPLATE_FULL (GstAudioFIRFilter, gst_audio_fir_filter, GstAudioFilter,
+    GST_TYPE_AUDIO_FX_BASE_FIR_FILTER, DEBUG_INIT);
+
+static void gst_audio_fir_filter_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+static void gst_audio_fir_filter_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec);
+static void gst_audio_fir_filter_finalize (GObject * object);
+
+static gboolean gst_audio_fir_filter_setup (GstAudioFilter * base,
+    GstRingBufferSpec * format);
+
+/* Element class */
+static void
+gst_audio_fir_filter_base_init (gpointer g_class)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+
+  gst_element_class_set_details_simple (element_class,
+      "Audio FIR filter", "Filter/Effect/Audio",
+      "Generic audio FIR filter with custom filter kernel",
+      "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
+}
+
+static void
+gst_audio_fir_filter_class_init (GstAudioFIRFilterClass * klass)
+{
+  GObjectClass *gobject_class = (GObjectClass *) klass;
+  GstAudioFilterClass *filter_class = (GstAudioFilterClass *) klass;
+
+  gobject_class->set_property = gst_audio_fir_filter_set_property;
+  gobject_class->get_property = gst_audio_fir_filter_get_property;
+  gobject_class->finalize = gst_audio_fir_filter_finalize;
+
+  g_object_class_install_property (gobject_class, PROP_KERNEL,
+      g_param_spec_value_array ("kernel", "Filter Kernel",
+          "Filter kernel for the FIR filter",
+          g_param_spec_double ("Element", "Filter Kernel Element",
+              "Element of the filter kernel", -G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
+              G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS),
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_LATENCY,
+      g_param_spec_uint64 ("latency", "Latecy",
+          "Filter latency in samples",
+          0, G_MAXUINT64, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  filter_class->setup = GST_DEBUG_FUNCPTR (gst_audio_fir_filter_setup);
+
+  /**
+   * GstAudioFIRFilter::rate-changed:
+   * @filter: the filter on which the signal is emitted
+   * @rate: the new sampling rate
+   *
+   * Will be emitted when the sampling rate changes. The callbacks
+   * will be called from the streaming thread and processing will
+   * stop until the event is handled.
+   */
+  gst_audio_fir_filter_signals[SIGNAL_RATE_CHANGED] =
+      g_signal_new ("rate-changed", G_TYPE_FROM_CLASS (klass),
+      G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstAudioFIRFilterClass, rate_changed),
+      NULL, NULL, gst_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
+}
+
+static void
+gst_audio_fir_filter_update_kernel (GstAudioFIRFilter * self, GValueArray * va)
+{
+  gdouble *kernel;
+  guint i;
+
+  gst_audio_fx_base_fir_filter_push_residue (GST_AUDIO_FX_BASE_FIR_FILTER
+      (self));
+
+  if (va) {
+    if (self->kernel)
+      g_value_array_free (self->kernel);
+
+    self->kernel = va;
+  }
+
+  kernel = g_new (gdouble, self->kernel->n_values);
+
+  for (i = 0; i < self->kernel->n_values; i++) {
+    GValue *v = g_value_array_get_nth (self->kernel, i);
+    kernel[i] = g_value_get_double (v);
+  }
+
+  gst_audio_fx_base_fir_filter_set_kernel (GST_AUDIO_FX_BASE_FIR_FILTER (self),
+      kernel, self->kernel->n_values, self->latency);
+}
+
+static void
+gst_audio_fir_filter_init (GstAudioFIRFilter * self,
+    GstAudioFIRFilterClass * g_class)
+{
+  GValue v = { 0, };
+  GValueArray *va;
+
+  self->latency = 0;
+  va = g_value_array_new (1);
+
+  g_value_init (&v, G_TYPE_DOUBLE);
+  g_value_set_double (&v, 1.0);
+  g_value_array_append (va, &v);
+  g_value_unset (&v);
+  gst_audio_fir_filter_update_kernel (self, va);
+
+  self->lock = g_mutex_new ();
+}
+
+/* GstAudioFilter vmethod implementations */
+
+/* get notified of caps and plug in the correct process function */
+static gboolean
+gst_audio_fir_filter_setup (GstAudioFilter * base, GstRingBufferSpec * format)
+{
+  GstAudioFIRFilter *self = GST_AUDIO_FIR_FILTER (base);
+
+  if (self->rate != format->rate) {
+    g_signal_emit (G_OBJECT (self),
+        gst_audio_fir_filter_signals[SIGNAL_RATE_CHANGED], 0, format->rate);
+    self->rate = format->rate;
+  }
+
+  return GST_AUDIO_FILTER_CLASS (parent_class)->setup (base, format);
+}
+
+static void
+gst_audio_fir_filter_finalize (GObject * object)
+{
+  GstAudioFIRFilter *self = GST_AUDIO_FIR_FILTER (object);
+
+  g_mutex_free (self->lock);
+  self->lock = NULL;
+
+  if (self->kernel)
+    g_value_array_free (self->kernel);
+  self->kernel = NULL;
+
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+gst_audio_fir_filter_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstAudioFIRFilter *self = GST_AUDIO_FIR_FILTER (object);
+
+  g_return_if_fail (GST_IS_AUDIO_FIR_FILTER (self));
+
+  switch (prop_id) {
+    case PROP_KERNEL:
+      g_mutex_lock (self->lock);
+      gst_audio_fx_base_fir_filter_push_residue (GST_AUDIO_FX_BASE_FIR_FILTER
+          (self));
+
+      gst_audio_fir_filter_update_kernel (self, g_value_dup_boxed (value));
+      g_mutex_unlock (self->lock);
+      break;
+    case PROP_LATENCY:
+      g_mutex_lock (self->lock);
+      self->latency = g_value_get_uint64 (value);
+      gst_audio_fir_filter_update_kernel (self, NULL);
+      g_mutex_unlock (self->lock);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_audio_fir_filter_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec)
+{
+  GstAudioFIRFilter *self = GST_AUDIO_FIR_FILTER (object);
+
+  switch (prop_id) {
+    case PROP_KERNEL:
+      g_value_set_boxed (value, self->kernel);
+      break;
+    case PROP_LATENCY:
+      g_value_set_uint64 (value, self->latency);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
diff --git a/gst/audiofx/audiofirfilter.h b/gst/audiofx/audiofirfilter.h
new file mode 100644 (file)
index 0000000..d1d896c
--- /dev/null
@@ -0,0 +1,72 @@
+/* 
+ * GStreamer
+ * Copyright (C) 2009 Sebastian Dröge <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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ * 
+ */
+
+#ifndef __GST_AUDIO_FIR_FILTER_H__
+#define __GST_AUDIO_FIR_FILTER_H__
+
+#include <gst/gst.h>
+#include <gst/audio/gstaudiofilter.h>
+
+#include "audiofxbasefirfilter.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_AUDIO_FIR_FILTER \
+  (gst_audio_fir_filter_get_type())
+#define GST_AUDIO_FIR_FILTER(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AUDIO_FIR_FILTER,GstAudioFIRFilter))
+#define GST_AUDIO_FIR_FILTER_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AUDIO_FIR_FILTER,GstAudioFIRFilterClass))
+#define GST_IS_AUDIO_FIR_FILTER(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AUDIO_FIR_FILTER))
+#define GST_IS_AUDIO_FIR_FILTER_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AUDIO_FIR_FILTER))
+
+typedef struct _GstAudioFIRFilter GstAudioFIRFilter;
+typedef struct _GstAudioFIRFilterClass GstAudioFIRFilterClass;
+
+/**
+ * GstAudioFIRFilter:
+ *
+ * Opaque data structure.
+ */
+struct _GstAudioFIRFilter {
+  GstAudioFXBaseFIRFilter parent;
+
+  GValueArray *kernel;
+  guint64 latency;
+
+  /* < private > */
+  GMutex *lock;
+  gint rate;
+};
+
+struct _GstAudioFIRFilterClass {
+  GstAudioFXBaseFIRFilterClass parent;
+
+  void (*rate_changed) (GstElement * element, gint rate);
+};
+
+GType gst_audio_fir_filter_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_AUDIO_FIR_FILTER_H__ */
index 43d1b0c..62b7076 100644 (file)
 #include "audiodynamic.h"
 #include "audiocheblimit.h"
 #include "audiochebband.h"
+#include "audioiirfilter.h"
 #include "audiowsincband.h"
 #include "audiowsinclimit.h"
+#include "audiofirfilter.h"
 
 /* entry point to initialize the plug-in
  * initialize the plug-in itself
@@ -60,10 +62,14 @@ plugin_init (GstPlugin * plugin)
           GST_TYPE_AUDIO_CHEB_LIMIT) &&
       gst_element_register (plugin, "audiochebband", GST_RANK_NONE,
           GST_TYPE_AUDIO_CHEB_BAND) &&
+      gst_element_register (plugin, "audioiirfilter", GST_RANK_NONE,
+          GST_TYPE_AUDIO_IIR_FILTER) &&
       gst_element_register (plugin, "audiowsinclimit", GST_RANK_NONE,
           GST_TYPE_AUDIO_WSINC_LIMIT) &&
       gst_element_register (plugin, "audiowsincband", GST_RANK_NONE,
-          GST_TYPE_AUDIO_WSINC_BAND));
+          GST_TYPE_AUDIO_WSINC_BAND) &&
+      gst_element_register (plugin, "audiofirfilter", GST_RANK_NONE,
+          GST_TYPE_AUDIO_FIR_FILTER));
 }
 
 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
diff --git a/gst/audiofx/audioiirfilter.c b/gst/audiofx/audioiirfilter.c
new file mode 100644 (file)
index 0000000..76112c6
--- /dev/null
@@ -0,0 +1,291 @@
+/* 
+ * GStreamer
+ * Copyright (C) 2009 Sebastian Dröge <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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ * 
+ */
+
+/**
+ * SECTION:element-audioiirfilter
+ * @short_description: Generic audio IIR filter
+ *
+ * <refsect2>
+ * <para>
+ * audioiirfilter implements a generic audio <ulink url="http://en.wikipedia.org/wiki/Infinite_impulse_response">IIR filter</ulink>. Before usage the
+ * "a" and "b" properties have to be set to the filter coefficients that
+ * should be used.
+ * </para>
+ * <para>
+ * The filter coefficients describe the numerator and denominator of the
+ * transfer function.
+ * </para>
+ * <para>
+ * To change the filter coefficients whenever the sampling rate changes the
+ * "rate-changed" signal can be used. This should be done for most
+ * IIR filters as they're depending on the sampling rate.
+ * </para>
+ * <title>Example application</title>
+ * <para>
+ * <include xmlns="http://www.w3.org/2003/XInclude" href="element-iirfilter-example.xml" />
+ * </para>
+ * </refsect2>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include <math.h>
+#include <gst/gst.h>
+#include <gst/audio/gstaudiofilter.h>
+#include <gst/controller/gstcontroller.h>
+
+#include "audioiirfilter.h"
+
+#define GST_CAT_DEFAULT gst_audio_iir_filter_debug
+GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
+
+enum
+{
+  SIGNAL_RATE_CHANGED,
+  LAST_SIGNAL
+};
+
+enum
+{
+  PROP_0,
+  PROP_A,
+  PROP_B
+};
+
+static guint gst_audio_iir_filter_signals[LAST_SIGNAL] = { 0, };
+
+#define DEBUG_INIT(bla) \
+  GST_DEBUG_CATEGORY_INIT (gst_audio_iir_filter_debug, "audioiirfilter", 0, \
+      "Generic audio IIR filter plugin");
+
+GST_BOILERPLATE_FULL (GstAudioIIRFilter, gst_audio_iir_filter, GstAudioFilter,
+    GST_TYPE_AUDIO_FX_BASE_IIR_FILTER, DEBUG_INIT);
+
+static void gst_audio_iir_filter_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+static void gst_audio_iir_filter_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec);
+static void gst_audio_iir_filter_finalize (GObject * object);
+
+static gboolean gst_audio_iir_filter_setup (GstAudioFilter * base,
+    GstRingBufferSpec * format);
+
+/* Element class */
+static void
+gst_audio_iir_filter_base_init (gpointer g_class)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+
+  gst_element_class_set_details_simple (element_class,
+      "Audio IIR filter", "Filter/Effect/Audio",
+      "Generic audio IIR filter with custom filter kernel",
+      "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
+}
+
+static void
+gst_audio_iir_filter_class_init (GstAudioIIRFilterClass * klass)
+{
+  GObjectClass *gobject_class = (GObjectClass *) klass;
+  GstAudioFilterClass *filter_class = (GstAudioFilterClass *) klass;
+
+  gobject_class->set_property = gst_audio_iir_filter_set_property;
+  gobject_class->get_property = gst_audio_iir_filter_get_property;
+  gobject_class->finalize = gst_audio_iir_filter_finalize;
+
+  g_object_class_install_property (gobject_class, PROP_A,
+      g_param_spec_value_array ("a", "A",
+          "Filter coefficients (numerator of transfer function)",
+          g_param_spec_double ("Coefficient", "Filter Coefficient",
+              "Filter coefficient", -G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
+              G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS),
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  g_object_class_install_property (gobject_class, PROP_B,
+      g_param_spec_value_array ("b", "B",
+          "Filter coefficients (denominator of transfer function)",
+          g_param_spec_double ("Coefficient", "Filter Coefficient",
+              "Filter coefficient", -G_MAXDOUBLE, G_MAXDOUBLE, 0.0,
+              G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS),
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  filter_class->setup = GST_DEBUG_FUNCPTR (gst_audio_iir_filter_setup);
+
+  /**
+   * GstAudioIIRFilter::rate-changed:
+   * @filter: the filter on which the signal is emitted
+   * @rate: the new sampling rate
+   *
+   * Will be emitted when the sampling rate changes. The callbacks
+   * will be called from the streaming thread and processing will
+   * stop until the event is handled.
+   */
+  gst_audio_iir_filter_signals[SIGNAL_RATE_CHANGED] =
+      g_signal_new ("rate-changed", G_TYPE_FROM_CLASS (klass),
+      G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstAudioIIRFilterClass, rate_changed),
+      NULL, NULL, gst_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT);
+}
+
+static void
+gst_audio_iir_filter_update_coefficients (GstAudioIIRFilter * self,
+    GValueArray * va, GValueArray * vb)
+{
+  gdouble *a = NULL, *b = NULL;
+  guint i;
+
+  if (va) {
+    if (self->a)
+      g_value_array_free (self->a);
+
+    self->a = va;
+  }
+  if (vb) {
+    if (self->b)
+      g_value_array_free (self->b);
+
+    self->b = vb;
+  }
+
+  if (self->a && self->a->n_values > 0)
+    a = g_new (gdouble, self->a->n_values);
+  if (self->b && self->b->n_values > 0)
+    b = g_new (gdouble, self->b->n_values);
+
+  if (self->a) {
+    for (i = 0; i < self->a->n_values; i++) {
+      GValue *v = g_value_array_get_nth (self->a, i);
+      a[i] = g_value_get_double (v);
+    }
+  }
+
+  if (self->b) {
+    for (i = 0; i < self->b->n_values; i++) {
+      GValue *v = g_value_array_get_nth (self->b, i);
+      b[i] = g_value_get_double (v);
+    }
+  }
+
+  gst_audio_fx_base_iir_filter_set_coefficients (GST_AUDIO_FX_BASE_IIR_FILTER
+      (self), a, (self->a) ? self->a->n_values : 0, b,
+      (self->b) ? self->b->n_values : 0);
+}
+
+static void
+gst_audio_iir_filter_init (GstAudioIIRFilter * self,
+    GstAudioIIRFilterClass * g_class)
+{
+  GValue v = { 0, };
+  GValueArray *a, *b;
+
+  a = g_value_array_new (1);
+
+  g_value_init (&v, G_TYPE_DOUBLE);
+  g_value_set_double (&v, 1.0);
+  g_value_array_append (a, &v);
+  g_value_unset (&v);
+
+  b = NULL;
+  gst_audio_iir_filter_update_coefficients (self, a, b);
+
+  self->lock = g_mutex_new ();
+}
+
+/* GstAudioFilter vmethod implementations */
+
+/* get notified of caps and plug in the correct process function */
+static gboolean
+gst_audio_iir_filter_setup (GstAudioFilter * base, GstRingBufferSpec * format)
+{
+  GstAudioIIRFilter *self = GST_AUDIO_IIR_FILTER (base);
+
+  if (self->rate != format->rate) {
+    g_signal_emit (G_OBJECT (self),
+        gst_audio_iir_filter_signals[SIGNAL_RATE_CHANGED], 0, format->rate);
+    self->rate = format->rate;
+  }
+
+  return GST_AUDIO_FILTER_CLASS (parent_class)->setup (base, format);
+}
+
+static void
+gst_audio_iir_filter_finalize (GObject * object)
+{
+  GstAudioIIRFilter *self = GST_AUDIO_IIR_FILTER (object);
+
+  g_mutex_free (self->lock);
+  self->lock = NULL;
+
+  if (self->a)
+    g_value_array_free (self->a);
+  self->a = NULL;
+  if (self->b)
+    g_value_array_free (self->b);
+  self->b = NULL;
+
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+gst_audio_iir_filter_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstAudioIIRFilter *self = GST_AUDIO_IIR_FILTER (object);
+
+  g_return_if_fail (GST_IS_AUDIO_IIR_FILTER (self));
+
+  switch (prop_id) {
+    case PROP_A:
+      g_mutex_lock (self->lock);
+      gst_audio_iir_filter_update_coefficients (self, g_value_dup_boxed (value),
+          NULL);
+      g_mutex_unlock (self->lock);
+      break;
+    case PROP_B:
+      g_mutex_lock (self->lock);
+      gst_audio_iir_filter_update_coefficients (self, NULL,
+          g_value_dup_boxed (value));
+      g_mutex_unlock (self->lock);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_audio_iir_filter_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec)
+{
+  GstAudioIIRFilter *self = GST_AUDIO_IIR_FILTER (object);
+
+  switch (prop_id) {
+    case PROP_A:
+      g_value_set_boxed (value, self->a);
+      break;
+    case PROP_B:
+      g_value_set_boxed (value, self->b);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
diff --git a/gst/audiofx/audioiirfilter.h b/gst/audiofx/audioiirfilter.h
new file mode 100644 (file)
index 0000000..607edf2
--- /dev/null
@@ -0,0 +1,71 @@
+/* 
+ * GStreamer
+ * Copyright (C) 2009 Sebastian Dröge <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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ * 
+ */
+
+#ifndef __GST_AUDIO_IIR_FILTER_H__
+#define __GST_AUDIO_IIR_FILTER_H__
+
+#include <gst/gst.h>
+#include <gst/audio/gstaudiofilter.h>
+
+#include "audiofxbaseiirfilter.h"
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_AUDIO_IIR_FILTER \
+  (gst_audio_iir_filter_get_type())
+#define GST_AUDIO_IIR_FILTER(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AUDIO_IIR_FILTER,GstAudioIIRFilter))
+#define GST_AUDIO_IIR_FILTER_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AUDIO_IIR_FILTER,GstAudioIIRFilterClass))
+#define GST_IS_AUDIO_IIR_FILTER(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AUDIO_IIR_FILTER))
+#define GST_IS_AUDIO_IIR_FILTER_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AUDIO_IIR_FILTER))
+
+typedef struct _GstAudioIIRFilter GstAudioIIRFilter;
+typedef struct _GstAudioIIRFilterClass GstAudioIIRFilterClass;
+
+/**
+ * GstAudioIIRFilter:
+ *
+ * Opaque data structure.
+ */
+struct _GstAudioIIRFilter {
+  GstAudioFXBaseIIRFilter parent;
+
+  GValueArray *a, *b;
+
+  /* < private > */
+  GMutex *lock;
+  gint rate;
+};
+
+struct _GstAudioIIRFilterClass {
+  GstAudioFXBaseIIRFilterClass parent;
+
+  void (*rate_changed) (GstElement * element, gint rate);
+};
+
+GType gst_audio_iir_filter_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_AUDIO_IIR_FILTER_H__ */
index d1a5519..5cc63db 100644 (file)
@@ -72,10 +72,12 @@ check_PROGRAMS = \
        elements/audioinvert \
        elements/audiochebband \
        elements/audiocheblimit \
+       elements/audioiirfilter \
        elements/audioamplify \
        elements/audiodynamic \
        elements/audiowsincband \
        elements/audiowsinclimit \
+       elements/audiofirfilter \
        elements/avimux \
        elements/avisubtitle \
        elements/deinterleave \
diff --git a/tests/check/elements/audiofirfilter.c b/tests/check/elements/audiofirfilter.c
new file mode 100644 (file)
index 0000000..c4eb723
--- /dev/null
@@ -0,0 +1,169 @@
+/* GStreamer
+ *
+ * Copyright (C) 2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 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
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <gst/gst.h>
+#include <gst/check/gstcheck.h>
+
+static gboolean have_eos = FALSE;
+
+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:
+    case GST_MESSAGE_WARNING:
+      g_assert_not_reached ();
+      g_main_loop_quit (loop);
+      break;
+
+    case GST_MESSAGE_EOS:
+      have_eos = TRUE;
+      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, };
+
+  fail_unless (rate > 0);
+
+  va = g_value_array_new (6);
+
+  g_value_init (&v, G_TYPE_DOUBLE);
+  g_value_set_double (&v, 0.0);
+  g_value_array_append (va, &v);
+  g_value_reset (&v);
+  g_value_set_double (&v, 0.0);
+  g_value_array_append (va, &v);
+  g_value_reset (&v);
+  g_value_set_double (&v, 0.0);
+  g_value_array_append (va, &v);
+  g_value_reset (&v);
+  g_value_set_double (&v, 0.0);
+  g_value_array_append (va, &v);
+  g_value_reset (&v);
+  g_value_set_double (&v, 0.0);
+  g_value_array_append (va, &v);
+  g_value_reset (&v);
+  g_value_set_double (&v, 1.0);
+  g_value_array_append (va, &v);
+  g_value_reset (&v);
+
+  g_object_set (G_OBJECT (element), "kernel", va, NULL);
+
+  g_value_array_free (va);
+}
+
+static gboolean have_data = FALSE;
+
+static void
+on_handoff (GstElement * object, GstBuffer * buffer, GstPad * pad,
+    gpointer user_data)
+{
+  if (!have_data) {
+    gdouble *data = (gdouble *) GST_BUFFER_DATA (buffer);
+
+    fail_unless (GST_BUFFER_SIZE (buffer) > 5 * sizeof (gdouble));
+    fail_unless (data[0] == 0.0);
+    fail_unless (data[1] == 0.0);
+    fail_unless (data[2] == 0.0);
+    fail_unless (data[3] == 0.0);
+    fail_unless (data[4] == 0.0);
+    fail_unless (data[5] != 0.0);
+    have_data = TRUE;
+  }
+}
+
+GST_START_TEST (test_pipeline)
+{
+  GstElement *pipeline, *src, *filter, *sink;
+  GstBus *bus;
+  GMainLoop *loop;
+
+  have_data = FALSE;
+  have_eos = FALSE;
+
+  pipeline = gst_element_factory_make ("pipeline", NULL);
+  fail_unless (pipeline != NULL);
+
+  src = gst_element_factory_make ("audiotestsrc", NULL);
+  fail_unless (src != NULL);
+  g_object_set (G_OBJECT (src), "num-buffers", 1000, NULL);
+
+  filter = gst_element_factory_make ("audiofirfilter", NULL);
+  fail_unless (filter != NULL);
+  g_signal_connect (G_OBJECT (filter), "rate-changed",
+      G_CALLBACK (on_rate_changed), NULL);
+
+  sink = gst_element_factory_make ("fakesink", NULL);
+  fail_unless (sink != NULL);
+  g_object_set (G_OBJECT (sink), "signal-handoffs", TRUE, NULL);
+  g_signal_connect (G_OBJECT (sink), "handoff", G_CALLBACK (on_handoff), NULL);
+
+  gst_bin_add_many (GST_BIN (pipeline), src, filter, sink, NULL);
+  fail_unless (gst_element_link_many (src, filter, sink, NULL));
+
+  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));
+
+  fail_if (gst_element_set_state (pipeline,
+          GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE);
+
+  g_main_loop_run (loop);
+
+  fail_unless (have_data);
+  fail_unless (have_eos);
+
+  fail_unless (gst_element_set_state (pipeline,
+          GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS);
+
+  g_main_loop_unref (loop);
+  gst_object_unref (pipeline);
+}
+
+GST_END_TEST;
+
+static Suite *
+audiofirfilter_suite (void)
+{
+  Suite *s = suite_create ("audiofirfilter");
+  TCase *tc_chain = tcase_create ("general");
+
+  suite_add_tcase (s, tc_chain);
+  tcase_add_test (tc_chain, test_pipeline);
+
+  return s;
+}
+
+GST_CHECK_MAIN (audiofirfilter);
diff --git a/tests/check/elements/audioiirfilter.c b/tests/check/elements/audioiirfilter.c
new file mode 100644 (file)
index 0000000..d144792
--- /dev/null
@@ -0,0 +1,179 @@
+/* GStreamer
+ *
+ * Copyright (C) 2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 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
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <gst/gst.h>
+#include <gst/check/gstcheck.h>
+
+static gboolean have_eos = FALSE;
+
+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:
+    case GST_MESSAGE_WARNING:
+      g_assert_not_reached ();
+      g_main_loop_quit (loop);
+      break;
+
+    case GST_MESSAGE_EOS:
+      have_eos = TRUE;
+      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, };
+
+  fail_unless (rate > 0);
+
+  va = g_value_array_new (6);
+
+  g_value_init (&v, G_TYPE_DOUBLE);
+  g_value_set_double (&v, 0.0);
+  g_value_array_append (va, &v);
+  g_value_reset (&v);
+  g_value_set_double (&v, 0.0);
+  g_value_array_append (va, &v);
+  g_value_reset (&v);
+  g_value_set_double (&v, 0.0);
+  g_value_array_append (va, &v);
+  g_value_reset (&v);
+  g_value_set_double (&v, 0.0);
+  g_value_array_append (va, &v);
+  g_value_reset (&v);
+  g_value_set_double (&v, 0.0);
+  g_value_array_append (va, &v);
+  g_value_reset (&v);
+  g_value_set_double (&v, 1.0);
+  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 (6);
+
+  g_value_set_double (&v, 0.0);
+  g_value_array_append (va, &v);
+  g_value_reset (&v);
+
+  g_object_set (G_OBJECT (element), "b", va, NULL);
+
+  g_value_array_free (va);
+}
+
+static gboolean have_data = FALSE;
+
+static void
+on_handoff (GstElement * object, GstBuffer * buffer, GstPad * pad,
+    gpointer user_data)
+{
+  if (!have_data) {
+    gdouble *data = (gdouble *) GST_BUFFER_DATA (buffer);
+
+    fail_unless (GST_BUFFER_SIZE (buffer) > 5 * sizeof (gdouble));
+    fail_unless (data[0] == 0.0);
+    fail_unless (data[1] == 0.0);
+    fail_unless (data[2] == 0.0);
+    fail_unless (data[3] == 0.0);
+    fail_unless (data[4] == 0.0);
+    fail_unless (data[5] != 0.0);
+    have_data = TRUE;
+  }
+}
+
+GST_START_TEST (test_pipeline)
+{
+  GstElement *pipeline, *src, *filter, *sink;
+  GstBus *bus;
+  GMainLoop *loop;
+
+  have_data = FALSE;
+  have_eos = FALSE;
+
+  pipeline = gst_element_factory_make ("pipeline", NULL);
+  fail_unless (pipeline != NULL);
+
+  src = gst_element_factory_make ("audiotestsrc", NULL);
+  fail_unless (src != NULL);
+  g_object_set (G_OBJECT (src), "num-buffers", 1000, NULL);
+
+  filter = gst_element_factory_make ("audioiirfilter", NULL);
+  fail_unless (filter != NULL);
+  g_signal_connect (G_OBJECT (filter), "rate-changed",
+      G_CALLBACK (on_rate_changed), NULL);
+
+  sink = gst_element_factory_make ("fakesink", NULL);
+  fail_unless (sink != NULL);
+  g_object_set (G_OBJECT (sink), "signal-handoffs", TRUE, NULL);
+  g_signal_connect (G_OBJECT (sink), "handoff", G_CALLBACK (on_handoff), NULL);
+
+  gst_bin_add_many (GST_BIN (pipeline), src, filter, sink, NULL);
+  fail_unless (gst_element_link_many (src, filter, sink, NULL));
+
+  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));
+
+  fail_if (gst_element_set_state (pipeline,
+          GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE);
+
+  g_main_loop_run (loop);
+
+  fail_unless (have_data);
+  fail_unless (have_eos);
+
+  fail_unless (gst_element_set_state (pipeline,
+          GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS);
+
+  g_main_loop_unref (loop);
+  gst_object_unref (pipeline);
+}
+
+GST_END_TEST;
+
+static Suite *
+audioiirfilter_suite (void)
+{
+  Suite *s = suite_create ("audioiirfilter");
+  TCase *tc_chain = tcase_create ("general");
+
+  suite_add_tcase (s, tc_chain);
+  tcase_add_test (tc_chain, test_pipeline);
+
+  return s;
+}
+
+GST_CHECK_MAIN (audioiirfilter);
index aad6dc1..1199543 100644 (file)
@@ -1,3 +1,3 @@
-SUBDIRS = equalizer level rtp spectrum
+SUBDIRS = audiofx equalizer level rtp spectrum
 
-DIST_SUBDIRS = equalizer level rtp spectrum
+DIST_SUBDIRS = audiofx equalizer level rtp spectrum
diff --git a/tests/examples/audiofx/Makefile.am b/tests/examples/audiofx/Makefile.am
new file mode 100644 (file)
index 0000000..efcf785
--- /dev/null
@@ -0,0 +1,7 @@
+noinst_PROGRAMS = firfilter-example iirfilter-example
+
+firfilter_example_CFLAGS = $(GST_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS)
+firfilter_example_LDADD = $(GST_LIBS) $(GST_PLUGINS_BASE_LIBS) -lgstfft-@GST_MAJORMINOR@ $(LIBM)
+
+iirfilter_example_CFLAGS = $(GST_CFLAGS)
+iirfilter_example_LDADD = $(GST_LIBS) $(LIBM)
diff --git a/tests/examples/audiofx/firfilter-example.c b/tests/examples/audiofx/firfilter-example.c
new file mode 100644 (file)
index 0000000..c5d56da
--- /dev/null
@@ -0,0 +1,161 @@
+/* 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/* This small sample application creates a bandpass FIR filter
+ * by transforming the frequency response to the filter kernel.
+ */
+
+#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 * M_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", 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;
+}
diff --git a/tests/examples/audiofx/iirfilter-example.c b/tests/examples/audiofx/iirfilter-example.c
new file mode 100644 (file)
index 0000000..8ccffb7
--- /dev/null
@@ -0,0 +1,137 @@
+/* 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, 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.
+ */
+
+#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 * M_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;
+}