Way, way, way too many files: Remove crack comment from the 2000 era.
[platform/upstream/gst-plugins-good.git] / gst / spectrum / gstspectrum.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23 #include <string.h>
24
25 #include "gstspectrum.h"
26
27 /* elementfactory information */
28 static GstElementDetails gst_spectrum_details =
29 GST_ELEMENT_DETAILS ("Spectrum analyzer",
30     "Filter/Analyzer/Audio",
31     "Run an FFT on the audio signal, output spectrum data",
32     "Erik Walthinsen <omega@cse.ogi.edu>");
33
34 /* Spectrum signals and args */
35 enum
36 {
37   /* FILL ME */
38   LAST_SIGNAL
39 };
40
41 enum
42 {
43   ARG_0,
44   ARG_WIDTH
45 };
46
47
48 static void gst_spectrum_base_init (gpointer g_class);
49 static void gst_spectrum_class_init (GstSpectrumClass * klass);
50 static void gst_spectrum_init (GstSpectrum * spectrum);
51
52 static void gst_spectrum_set_property (GObject * object, guint prop_id,
53     const GValue * value, GParamSpec * pspec);
54
55 static void gst_spectrum_chain (GstPad * pad, GstData * _data);
56
57 #define fixed short
58 int gst_spectrum_fix_fft (fixed fr[], fixed fi[], int m, int inverse);
59 void gst_spectrum_fix_loud (fixed loud[], fixed fr[], fixed fi[], int n,
60     int scale_shift);
61 void gst_spectrum_window (fixed fr[], int n);
62
63
64 static GstElementClass *parent_class = NULL;
65
66 /*static guint gst_spectrum_signals[LAST_SIGNAL] = { 0 }; */
67
68 GType
69 gst_spectrum_get_type (void)
70 {
71   static GType spectrum_type = 0;
72
73   if (!spectrum_type) {
74     static const GTypeInfo spectrum_info = {
75       sizeof (GstSpectrumClass),
76       gst_spectrum_base_init,
77       NULL,
78       (GClassInitFunc) gst_spectrum_class_init,
79       NULL,
80       NULL,
81       sizeof (GstSpectrum),
82       0,
83       (GInstanceInitFunc) gst_spectrum_init,
84     };
85
86     spectrum_type =
87         g_type_register_static (GST_TYPE_ELEMENT, "GstSpectrum", &spectrum_info,
88         0);
89   }
90   return spectrum_type;
91 }
92
93 static void
94 gst_spectrum_base_init (gpointer g_class)
95 {
96   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
97
98   gst_element_class_set_details (element_class, &gst_spectrum_details);
99 }
100 static void
101 gst_spectrum_class_init (GstSpectrumClass * klass)
102 {
103   GObjectClass *gobject_class;
104
105   gobject_class = (GObjectClass *) klass;
106
107   parent_class = g_type_class_ref (GST_TYPE_ELEMENT);
108
109   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_WIDTH, g_param_spec_int ("width", "width", "width", G_MININT, G_MAXINT, 0, G_PARAM_WRITABLE));   /* CHECKME */
110
111   gobject_class->set_property = gst_spectrum_set_property;
112 }
113
114 static void
115 gst_spectrum_init (GstSpectrum * spectrum)
116 {
117   spectrum->sinkpad = gst_pad_new ("sink", GST_PAD_SINK);
118   gst_element_add_pad (GST_ELEMENT (spectrum), spectrum->sinkpad);
119   gst_pad_set_chain_function (spectrum->sinkpad, gst_spectrum_chain);
120   spectrum->srcpad = gst_pad_new ("src", GST_PAD_SRC);
121   gst_element_add_pad (GST_ELEMENT (spectrum), spectrum->srcpad);
122
123   spectrum->width = 75;
124 }
125
126 static void
127 gst_spectrum_set_property (GObject * object, guint prop_id,
128     const GValue * value, GParamSpec * pspec)
129 {
130   GstSpectrum *spectrum;
131
132   g_return_if_fail (GST_IS_SPECTRUM (object));
133   spectrum = GST_SPECTRUM (object);
134
135   switch (prop_id) {
136     case ARG_WIDTH:
137       spectrum->width = g_value_get_int (value);
138       break;
139     default:
140       break;
141   }
142 }
143
144 static void
145 gst_spectrum_chain (GstPad * pad, GstData * _data)
146 {
147   GstBuffer *buf = GST_BUFFER (_data);
148   GstSpectrum *spectrum;
149   gint spec_base, spec_len;
150   gint16 *re, *im, *loud;
151   gint16 *samples;
152   gint step, pos, i;
153   guchar *spect;
154   GstBuffer *newbuf;
155
156   g_return_if_fail (pad != NULL);
157   g_return_if_fail (GST_IS_PAD (pad));
158   g_return_if_fail (buf != NULL);
159
160   spectrum = GST_SPECTRUM (GST_OBJECT_PARENT (pad));
161
162   samples = (gint16 *) GST_BUFFER_DATA (buf);
163
164   spec_base = 8;
165   spec_len = 1024;
166
167   im = g_malloc (spec_len * sizeof (gint16));
168   g_return_if_fail (im != NULL);
169   loud = g_malloc (spec_len * sizeof (gint16));
170   g_return_if_fail (loud != NULL);
171
172   memset (im, 0, spec_len * sizeof (gint16));
173   /*if (spectrum->meta->channels == 2) { */
174   re = g_malloc (spec_len * sizeof (gint16));
175   for (i = 0; i < spec_len; i++)
176     re[i] = (samples[(i * 2)] + samples[(i * 2) + 1]) >> 1;
177   /*} else */
178   /*  re = samples; */
179   gst_spectrum_window (re, spec_len);
180   gst_spectrum_fix_fft (re, im, spec_base, FALSE);
181   gst_spectrum_fix_loud (loud, re, im, spec_len, 0);
182   if (re != samples)
183     g_free (re);
184   g_free (im);
185   step = spec_len / (spectrum->width * 2);
186   spect = (guchar *) g_malloc (spectrum->width);
187   for (i = 0, pos = 0; i < spectrum->width; i++, pos += step) {
188     if (loud[pos] > -60)
189       spect[i] = (loud[pos] + 60) / 2;
190     else
191       spect[i] = 0;
192 /*    if (spect[i] > 15); */
193 /*      spect[i] = 15; */
194   }
195   g_free (loud);
196   gst_buffer_unref (buf);
197 /*  g_free(samples); */
198
199   newbuf = gst_buffer_new ();
200   g_return_if_fail (newbuf != NULL);
201   GST_BUFFER_DATA (newbuf) = spect;
202   GST_BUFFER_SIZE (newbuf) = spectrum->width;
203
204   gst_pad_push (spectrum->srcpad, GST_DATA (newbuf));
205 }
206
207 static gboolean
208 plugin_init (GstPlugin * plugin)
209 {
210   return gst_element_register (plugin, "spectrum", GST_RANK_NONE,
211       GST_TYPE_SPECTRUM);
212 }
213
214 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
215     GST_VERSION_MINOR,
216     "spectrum",
217     "Run an FFT on the audio signal, output spectrum data",
218     plugin_init, VERSION, GST_LICENSE, GST_PACKAGE, GST_ORIGIN)